Shapeless и gremlin scala: как вернуть результат вызова в `as`?

Итак, я вызываю эту функцию as (от gremlin-scala):

case class GremlinScala[End, Labels <: HList](traversal: GraphTraversal[_, End]) {
  def as(name: String, moreNames: String*)(implicit p: Prepend[Labels, End :: HNil]) =
    GremlinScala[End, p.Out](traversal.as(name, moreNames: _*))
}

Это определяется здесь: https://github.com/mpollmeier/gremlin-scala/blob/master/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala

Требуется неявный аргумент Prepend, который я не уверен, что понимаю. я знаю это gremlin-scala использует свой HList, чтобы отслеживать, какие точки в запросе as называется, так что позже, когда select называется он знает, какие точки в обходе, чтобы вернуться.

Это ключ: as добавляет к этому HList. Или, видимо, претендует, в зависимости от обстоятельств.

Это нормально работает в общем коде, но теперь я хочу написать функцию, которая вызывает as и возвращает свой результат. Вот где я застрял: что является сигнатурой возвращаемого значения этой функции?

Наконец, я добавил в свою функцию неявный параметр, но боюсь, что только что преследовал проблему до уровня. Вот что у меня так далеко:

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)
  }
}

Это делает его компиляцией, но я все еще не могу использовать эту функцию! Всякий раз, когда я это называю, мне жалуется, что

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

Как мне написать функцию, которая возвращает результат asи какая у него подпись?

Спасибо!

1 ответ

Решение

Как вы правильно объясните, причина, по которой мы используем prepend, состоит в том, чтобы сохранить типы шагов, помеченные как as, Он держит их в обратном порядке, поскольку его легче обрабатывать с обеих сторон: для захвата и воспроизведения.

Итак implicit p: Prepend[Labels, End :: HNil] на текущем шаге добавляется тип, чтобы он был захвачен во втором параметре типа (и мы можем использовать его на последующих шагах, например, select).

Насколько я вижу, ты делаешь совершенно правильные вещи, и это на самом деле работает... в любом случае для меня:)

Это компилирует:

import gremlin.scala._
import shapeless.{HNil, ::}
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory
def graph = TinkerFactory.createModern.asScala
val gs1: GremlinScala[Vertex, Vertex :: HNil] = graph.V().as("a")
val gs2: GremlinScala[Vertex, Vertex :: HNil] = AsOperation("someLabel").operate(graph.V())
Другие вопросы по тегам