ib8*_*b84 3 scala typelist hlist shapeless klist
我发现了HList/KList,它们非常酷.我有一个实际的用例,其中具有保守类型信息的异构类型和可变长度容器将非常有用(更多信息,请参见下面的背景).但是,我还没有将H/KList的用法理解为方法参数,在这里我被迫完全键入 - 注释参数或松散类型信息.H/KLists甚至可以用作参数,如果完整类型当然不知道?如何在不丢失类型信息的情况下引用H/KList?
"类型列表"可以用来指代异构和可变长度类型参数的元组吗?在这里它说:
... the types of the elements can be tracked separate from the actual element values. To do this we create an purely abstract type (it has no instances) which models a list of types, let's call it TList.
我玩了它,但还没有理解如何使用它作为参数的类型注释HList.
基本上,我想要这样的东西:
implicit def hlistToTypedLink[TL](a: HList[TL]):TypedLink[TL] = new TypedLink[TL](a.map(a:X => new TypedHandle[X]))
Run Code Online (Sandbox Code Playgroud)
其中TL指的是Type List,X指的是当前元素的类型.所以这里的HList应该映射到另一个类似于Tuple的容器TypedLink,由类型列表TL进行参数化.元素将被包装在另一个参数化容器TypedHandle中,使用当前类型X键入.
这可能吗?
我看到了Shapeless的'HList及其"统一"方法,但问题仍然存在:除了可变长度之外,我不知道如何在参数列表中引用它.
我的第二个希望是使用KList.它适用于我的情况,因为TypedHandle是具有相同构造函数的公共容器.随着KLIST它似乎更容易输入注释,根据apocalisp:
val m = List(1, 2, 3, 4) :^: List("str1", "str2") :^: KNil
Run Code Online (Sandbox Code Playgroud)
将是类型:
KCons[Int,java.lang.String :: HNil,List]
Run Code Online (Sandbox Code Playgroud)
但问题仍然存在:在方法定义中,我不知道它是否会是一个
KCons[String, Int :: HNil, TH]
Run Code Online (Sandbox Code Playgroud)
或者a
KCons[Foo, Bar, Baz :: HNil, TH]
Run Code Online (Sandbox Code Playgroud)
所以我不知道如何键入注释KList作为方法参数.
谢谢你的任何提示!
背景:我正在为优秀的OO-和图形数据库hypergraphdb编写scala便利扩展.Hypergraphdb的超边界,HGLink,基本上是HGHandle的元组.HGHandle指的是本身键入的原子.因此,HGLink本身将是异质类型并且具有可变长度.但是,HGLink的实现到目前为止都是无类型的,并且是由HGHandle的无类型实现构建的.我猜java的类型系统没有足够的表现力来反映hypergraphdb的(远远优越的)类型系统(例如,它也有更高的kinded类型).
基本上,我正在尝试使用hypergraphdb的类型系统来桥接scala,我正在学习很多东西,直到现在这真的很有趣.除了许多其他黑客之外,TypedHandle已经很好用了.
谢谢你的建议.
我并不完全清楚你要求的是什么,但是hlistToTypedLink看起来它可以使用无形HList和多态函数值来处理,
scala> import shapeless._ ; import TypeOperators._
import shapeless._
import TypeOperators._
scala> class TypedHandle[T]
defined class TypedHandle
scala> class TypedLink[L <: HList](l : L)
defined class TypedLink
scala> object MkTypedHandle extends (Id ~> TypedHandle) {
| def apply[T](t : T) = new TypedHandle[T]
| }
defined module MkTypedHandle
scala> def hlistToTypedLink[L <: HList, M <: HList](a: L)
| (implicit mapper: MapperAux[MkTypedHandle.type, L, M]) =
| new TypedLink[M](a map MkTypedHandle)
hlistToTypedLink: [L <: HList, M <: HList](a: L)
(implicit mapper: MapperAux[MkTypedHandle.type,L,M])TypedLink[M]
scala> hlistToTypedLink(23 :: "foo" :: true :: HNil)
res0: TypedLink[TypedHandle[Int] :: TypedHandle[String] ::
TypedHandle[Boolean] :: HNil] = TypedLink@51fb5716
Run Code Online (Sandbox Code Playgroud)
从本质上讲,你看起来想要映射你的参数HList a,将每个元素包装在一个TypedHandle然后将结果包装成HList一个TypedLink.在所有情况下,包装器都要精确地根据其内容的类型进行参数化.
如上所示,这可以使用无形的HList map.这里有两个关键因素.首先,将多态函数样值的定义MkTypedHandle,其可以在整个被映射HList a创建HList的TypedLink-wrapped元件.第二,mapper驱动地图操作的隐含见证.