(可选)在无形状中修改大小列表的头部

时间:2016-05-23 06:50:29

标签: scala shapeless

给出Sized列表。如果它存在,怎么可以选择修改头?

也就是说,如何定义ff:

def addOneToHeadIfExists[N <: Nat](l: Sized[IndexedSeq[Int], N]): Sized[IndexedSeq[Int], N] = ???

也就是说,我可以打电话:

val x: Sized[IndexedSeq[Int], _3] = Sized(1, 2, 3)
addOneToHeadIfExists(x) // gives Sized(2, 2, 3)

val y: Sized[IndexedSeq[Int], _0] = Sized() // sample. doesn't actually compile
addOneToHeadIfExists(x) // gives Sized()

1 个答案:

答案 0 :(得分:1)

无形大小类型的主要目的是在编译时提供有关值的足够信息,以便不需要对此类属性进行运行时测试。

验证大小的集合是非空的,因此headtail定义明确是非常简单的,并且是无形的情况之一,其中隐式证据不是立即的必要。这是因为我们可以通过在length类型参数中要求至少一个外部Succ类型构造函数来捕获序列大小大于0的约束。

这给了我们,

def addOneToHead[N <: Nat](l: Sized[IndexedSeq[Int], Succ[N]]):
  Sized[IndexedSeq[Int], Succ[N]] = (l.head+1) +: l.tail

此方法是针对所有Succ[N]的长度为N的大小序列定义的,其中NNat,即所有大于0的nat。

示例REPL会话,

scala> addOneToHead(Sized(1, 2, 3))
res0: shapeless.Sized[IndexedSeq[Int],shapeless.Succ[shapeless.nat._2]] =
      Vector(2, 2, 3)

scala> addOneToHead(Sized())
<console>:16: error: polymorphic expression cannot be instantiated to expected type
 found   : [CC[_]]shapeless.Sized[CC[Nothing],shapeless._0]
 required: shapeless.Sized[IndexedSeq[Int],shapeless.Succ[?]]
   addOneToHead(Sized())
                         ^

正如您所看到的,这是一个类型错误,因为对于任何nat类型_0,编译器无法将类型Succ[N]N统一起来。