Scala,gremlin-scala,HLists,Poly2,RightFold和缺少的隐式Prepend [英] Scala, gremlin-scala, HLists, Poly2, RightFold and a missing implicit Prepend

查看:90
本文介绍了Scala,gremlin-scala,HLists,Poly2,RightFold和缺少的隐式Prepend的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在尝试将gremlin-scala的一系列操作封装为HList,以便可以对它们进行RightFold(这将使我可以将gremlin查询构造为数据:特别是Operations中).

So, I am trying to encapsulate a series of operations from gremlin-scala into an HList so I can do a RightFold over them (this would allow me to construct a gremlin query as data: specifically an HList of Operations).

这是我的意思:通常您可以像这样呼叫gremlin-scala:

Here is what I mean: usually you can make a call to gremlin-scala like so:

import gremlin.scala._
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory

def graph = TinkerFactory.createModern.asScala
graph.V.hasLabel("person").out("created").as("creations").toList.map(_.valueMap)

---> List[Map[String,Any]] = List(Map(name -> lop, lang -> java), Map(name -> ripple, lang -> java), Map(name -> lop, lang -> java), Map(name -> lop, lang -> java))

这一切都很好,但是我希望能够将查询构造为数据.我将其建模为OperationsHList,如下所示:

This is all well and good, but I want to be able to construct a query as data. I am modeling this as an HList of Operations like so:

sealed trait Operation

case class VertexOperation[Labels <: HList](vertex: String) extends Operation {
  def operate(graph: Graph): GremlinScala[Vertex, Labels] = {
    graph.V.hasLabel(vertex).asInstanceOf[GremlinScala[Vertex, Labels]]
  }
}

case class OutOperation[Labels <: HList](out: String) extends Operation {
  def operate(vertex: GremlinScala[Vertex, Labels]): GremlinScala[Vertex, Labels] = {
    vertex.out(out)
  }
}

然后我可以通过将它们放在HList中来创建查询,如下所示:

Then I would be able to create a query by putting these in an HList like so:

import shapeless._

val query = OutOperation("created") :: VertexOperation("person") :: HNil

现在我将它们放在HList中,可以执行RightFold来将它们一个一个地应用于图形:

Now that I have these in an HList, I can do a RightFold to apply them one by one to the graph:

trait ApplyOperationDefault extends Poly2 {
  implicit def default[T, L <: HList] = at[T, L] ((_, acc) => acc)
}

object ApplyOperation extends ApplyOperationDefault {
  implicit def vertex[T, L <: HList, S <: HList] = at[VertexOperation[S], Graph] ((t, acc) => t.operate(acc))
  implicit def out[T, L <: HList, S <: HList] = at[OutOperation[S], GremlinScala[Vertex, S]] ((t, acc) => t.operate(acc))
}

object Operation {
  def process[Input, Output, A <: HList](operations: A, input: Input) (implicit folder: RightFolder.Aux[A, Input, ApplyOperation.type, Output]): Output = {
    operations.foldRight(input) (ApplyOperation)
  }
}

并这样称呼它:

val result = Operation.process(query, graph).toList

这一切有效!并显示出很大的希望.

This all works! And shows great promise.

这是我要解决的问题:当我尝试通过as操作执行此操作时,我可以获取Operation进行编译:

Here is where I get to my issue: when I try to do this with the as operation, I can get the Operation to compile:

case class AsOperation[A, In <: HList](step: String) extends Operation {
  def operate(g: GremlinScala[A, In]) (implicit p: Prepend[In, ::[A, HNil]]): GremlinScala[A, p.Out] = {
    g.as(step)
  }
}

(我在其中添加了(implicit p: Prepend[In, ::[A, HNil]]),因为编译器另有抱怨)...但是当我尝试为这种情况以及其他情况创建隐式处理程序时,它会失败:

(I added that (implicit p: Prepend[In, ::[A, HNil]]) in there because the compiler was complaining otherwise)... but when I try to create the implicit handler for this case along with the others, it fails:

implicit def as[T, L <: HList, A, In <: HList] = at[AsOperation[A, In], GremlinScala[A, In]] ((t, acc) => t.operate(acc))

---> could not find implicit value for parameter p: shapeless.ops.hlist.Prepend[In,shapeless.::[A,shapeless.HNil]]

因此,这里有几个问题:

So, several questions here:

  • 此隐式Prepend的全部含义是什么,为什么我需要它?
  • 为什么在正常调用as时能够找到隐式Prepend,但是在尝试通过RightFold时却找不到它?
  • 如何创建Prepend的隐式实例?
  • 创建后,如何将其传递给operate的调用?
  • 执行此操作的正确方法是什么?
  • What is this implicit Prepend all about, and why do I need it?
  • Why is it able to find the implicit Prepend when calling as normally, but fails when trying to RightFold over it?
  • How do I create an implicit instance of Prepend?
  • Once created, how would I pass it in to the invocation of operate?
  • What is the right way to do this??

我可能还有其他问题,但这是主要的问题.我一直在阅读类型级别的编程和总体上没有形状的东西,我真的很喜欢它,但是这种东西令人发疯.我知道这里缺少一些微妙的类型,但是很难知道从哪里开始破译什么.

I probably have more questions, but these are the main ones. I have been reading up on type-level programming and shapeless in general, and I really kind of love it, but this kind of stuff is maddening. I know there is some subtle type thing I am missing here, but it is hard to know where to start deciphering what is missing.

感谢您的帮助!我真的很想爱scala和无形的人,希望能尽快克服这个障碍.

Thanks for any help! I truly want to love scala and shapeless, hoping to get over this obstacle soon.

我做了一个最小的仓库,在这里重现了这个问题: https://github.com/bmeg/leprechaun

I made a minimal repo reproducing the problem here: https://github.com/bmeg/leprechaun

希望有帮助!

推荐答案

您的误解是使用Prepend.编译器将自动为您生成它,您无需手动创建它.

Your misunderstanding is the use of Prepend. The compiler will generate it for you automatically, you don't ever need to create it manually.

Prepend用于保留标记步骤的类型. gremlin-scala readme.md更深入.

As mentioned in Shapeless and gremlin scala: How do I return the result of a call to `as`? Prepend is used to keep the types of the labelled steps. The gremlin-scala readme.md goes into more depth.

实际上,编译器会告诉您所需的信息: could not find implicit value for parameter p: shapeless.ops.hlist.Prepend[In,shapeless.::[A,shapeless.HNil]]

The compiler actually tells you exactly what it needs: could not find implicit value for parameter p: shapeless.ops.hlist.Prepend[In,shapeless.::[A,shapeless.HNil]]

这就是我所做的:将一个隐式的Prepend添加到范围中:) 我刚刚给您发送了 PR ,现在可以正常编译了.

So that's what I did: add an implicit Prepend to the scope :) I just sent you a PR, it compiles fine now.

PS:您可能想要更新gremlin-scala的版本.

PS: You might want to update your versions of gremlin-scala.

这篇关于Scala,gremlin-scala,HLists,Poly2,RightFold和缺少的隐式Prepend的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆