Итак, я пытаюсь инкапсулировать серию операций с gremlin-scala
в HList
так что я могу сделать RightFold
над ними (это позволило бы мне построить запрос гремлина как данные: конкретно HList
от Operations
).Scala, гном-Скала, HLists, poly2, RightFold и недостающий неявное PREPEND
Вот что я имею в виду: как правило, вы можете сделать вызов gremlin-scala
так:
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))
Это все хорошо, но я хочу, чтобы иметь возможность построить запрос в виде данных. Я моделирования это как HList
из Operations
как так:
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
так:
import shapeless._
val query = OutOperation("created") :: VertexOperation("person") :: HNil
Теперь, когда я их в HList
, я могу сделать RightFold
применять их по одному графику:
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
Все это работает! И показывает большие надежды.
Вот где я получаю на мой вопрос: когда я пытаюсь сделать это с помощью as
операции, я могу получить Operation
компиляции:
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]])
там, потому что компилятор жалуясь иначе) ... но когда я пытаюсь создать неявную обработчик для этого случая, наряду с другими, он не:
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]]
Итак, несколько вопросов здесь:
- Что это такое неявное
Prepend
все о том, зачем оно мне нужно? - Почему он может найти неявный
Prepend
при вызовеas
нормально, но сбой при попыткеRightFold
над ним? - Как создать неявный экземпляр
Prepend
? - Как только я создал, как бы передать его вызову
operate
? - Что такое правильный способ?
У меня, наверное, больше вопросов, но это основные. Я читал в основном программирование на типе и бесформенное вообще, и я действительно люблю его, но этот вид сумасшествия. Я знаю, что есть какая-то тонкая вещь, которую я здесь отсутствует, но трудно понять, с чего начать дешифровать то, чего не хватает.
Спасибо за помощь! Я действительно хочу любить скала и бесформенность, надеясь скоро преодолеть это препятствие.
EDIT: Я сделал минимальное репо воспроизводя проблему здесь: https://github.com/bmeg/leprechaun
Хотелось бы надеяться, что помогает!
Интересно ... теперь любая функция, которую я называю этим методом 'as', мне также нужно объявить неявным' Prepend'. Любой способ избежать этого бесконечного регресса? В какой момент создается «Prepend»? – prismofeverything
переместил обсуждение на https://gitter.im/mpollmeier/gremlin-scala –