I'm trying to figure out how to associate a feature (singleton type) of shapeless with another (HList), assuming we would like to derive a generic type Vector
that contains information about the arity of the input vector:
package com.tribbloids.spike.shapeless_spike.shapesafe
import shapeless.{Generic, Witness}
import scala.language.implicitConversions
trait Vector[W <: Witness.Lt[Int]] extends Serializable {
def witness: W
def <*>(that: Vector[W]): Vector[W] = ???
}
object Vector {
case class Impl[W <: Witness.Lt[Int]](witness: W) extends Vector[W] {}
def zeros[W <: Witness.Lt[Int]](witness: W): Impl[W] = Impl(witness)
object Attempt1 {
def values(v: (Double)) = Impl(Witness(1))
def values(v: (Double, Double)) = Impl(Witness(2))
def values(v: (Double, Double, Double)) = Impl(Witness(3))
Vector.zeros(Witness(2)) <*> values(2.0, 3.0)
Vector.zeros(Witness(3)) <*> values(2.0, 3.0) // breaks as expected
}
}
I can write numerous lines to support the derivation (which will eventually hit the JVM's limitation for classloading), or I can write a more succinct implicit conversion to dynamically crate singleton types on-demand, something like this:
object Attempt2 {
type HInts = Int :: HInts
def values[T <: Product](v: T)(implicit aux: Generic.Aux[T, HInts]) = {
???
}
}
However, despite that both are very matured shapeless feature, it seems to have no documentation teaching how to enable such algebraic type derivation.
Is there an easy way to replace all my implicit functions with a general enough statement? I'm using scala-2.12 + shapeless 2.3 at the moment.
Thanks a lot for the information.
HList
/Coproduct
size inNat
. Problem is how to convertNat
toInt
singleton (Witness
). It it really important for you to have values asWitness
types? – Mateusz Kubuszoktrait NatToWitness[N <: Nat] { type W <: Witness.Lt[Int]; def witness(): W }
, and then use build-in tooling to make HList -> Size -> NatToWitness -> W conversion, but I am not sure if you would be interested in such solution. – Mateusz Kubuszok