Pregunta

I discovered HList / KList, they are pretty cool. I have an actual use case, in which heterogenously typed and variable length containers with conserved type information would be very useful (for more info, see background below). However, I haven't understood the usage of a H/KList as method parameter, where I'm forced to fully type-annotate the parameter or loose type information. Can H/KLists even be used as a parameter, if the full type is, of course, not known? How to refer to a H/KList without loosing the type information?

Could "type lists" be used to refer to a tuple of heterogenous & variable length type parameters? Here it says: ... 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. I played around with it, but haven't not yet understood how to use it for type annotation of an HList as parameter.

Basically, I want something like this:

implicit def hlistToTypedLink[TL](a: HList[TL]):TypedLink[TL] = new TypedLink[TL](a.map(a:X => new TypedHandle[X]))

where TL refers to the Type List and X to the type of the current element. So here a HList should be mapped to another Tuple-like container, TypedLink, parametrized by the type list TL. The elements are to be wrapped each in yet another parametrized container TypedHandle, typed with the current type X.

Is this possible?

I saw Shapeless' HList and its "unify" method but the problem remains the same: I don't know how to refer to it in the parameter list, besides variable length.

My second hope was to use KList. It applies in my case, because TypedHandle is a common container with same constructor. With KList it appears easier to type annotate, according to apocalisp:

 val m = List(1, 2, 3, 4) :^: List("str1", "str2") :^: KNil

would be of type:

 KCons[Int,java.lang.String :: HNil,List]

However, the problem remains the same: In the method definition, I cannot know whether it will be a

KCons[String, Int :: HNil, TH]

or a

KCons[Foo, Bar, Baz :: HNil, TH]

so I don't know how to type annotate the KList as method parameter either.

Thanks for any hints!

Background: I'm writing scala convenience extensions for the excellent OO- & graph database hypergraphdb. Hypergraphdb's hyperedges, HGLink, are basically tuples of HGHandle's. HGHandle refer to atoms which per se are typed. Hence HGLink per se would be heterogenously typed and of variable length. However, HGLink's implementations are till now untyped, and constructed by untyped implementations of HGHandle's. I guess java's typesystem is not expressive enough to reflect the (far superior) typesystem of hypergraphdb (which for example, also has higher kinded types).

Basically, I'm trying to bridge scala's with hypergraphdb's type systems, I'm learning a lot and till now this has been real fun. TypedHandle works great already, besides numerous other hacks.

thanks for any advice.

¿Fue útil?

Solución

It's not completely clear to me what you're asking for, but your hlistToTypedLink looks like it could be handled using shapeless's HList and polymorphic function values,

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

Essentially it looks like you want to map over your argument HList a, wrapping each element in a TypedHandle and then wrapping the resulting HList in a TypedLink. In all cases the wrappers are to be parametrized precisely on the types of their contents.

As seen above, this is possible using shapeless's HList map. There are two key ingredients here. First, the definition of the polymorphic function-like value MkTypedHandle which can be mapped across the HList a creating an HList of TypedLink-wrapped elements. And second, the implicit witness mapper which drives the map operation.

Otros consejos

I better respond as you refer to my blog post. A TList is simply a HList without value storage, i.e. there is only a type representation of the list, no runtime representation. One advantage is that it facilitates different, possibly more efficient, types of value storage, for example arrays (HArray in Metascala). TLists can also be used to model union types (basically type sets), however Scala's type system is not powerful enough to do this solely on the type level (Haskell's type system is I think).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top