St. St. - 1 year ago 69
Scala Question

The length of HList type paremeter in terms of Nat

Suppose I have a method without params. How can I determine a length of type parameter?

def func[T <: HList]: Nat = {
// some magic

Answer Source

You can use ops.hlist.Length operation to calculate the Nat length of an HList.

Also, getting it as an opaque Nat is not very useful, because you lose all the type-level information about the actual number. So you have to get the exact Nat type from the function:

import shapeless._
import shapeless.ops.hlist.Length

def func[T <: HList](implicit len: Length[T]): len.Out = len()


scala> natLen[Int :: String :: HNil]
res1: shapeless.Succ[shapeless.Succ[shapeless._0]] = Succ()

Getting the length as an Int seems more tricky. It seems you can't use ops.nat.ToInt, because it would require a N <: Nat type parameter and basically make it useless:

def uselessIntLen[T <: HList, N <: Nat](implicit 
  len: Length.Aux[T, N], 
  toInt: ToInt[N]
): Int = toInt()

I've found the following workaround using HKernel (of course, it's also possible to write a new typeclass IntLength manually). Maybe someone can help with a more direct built-in method:

import shapeless.ops.hlist.HKernelAux 

def intLen[T <: HList](implicit ker: HKernelAux[T]): Int = ker().length


scala> intLen[Int :: String :: HNil]
res2: Int = 2