2016-11-19 51 views
2

我想打印皮亚诺的数字,这样的事情:有没有办法用类型做递归隐式def?

sealed trait Nat 
trait _0 extends Nat 
trait Succ[N <: Nat] extends Nat 

type _1 = Succ[_0] 
type _2 = Succ[_1] 

class RepNat[T <: Nat](val value: Int) 
def rep[T <: Nat](implicit r: RepNat[T]) = r.value 
implicit val repZero = new RepNat[_0](0) 
implicit def repSucc[A <: Succ[B], B <: Nat](implicit r: RepNat[B]): RepNat[A] = new RepNat[A](r.value + 1) 
println(rep[_0]) 
println(rep[_1]) 
// does not work, implicits do not resolve recursively: 
// implicitly[RepNat[_2]] 
// println(rep[_2]) 

// but explicit instantiation works: 
println(rep[_2](repSucc(implicitly[RepNat[_1]]))) 

回答

3

递归implicits做的工作。下面定义_2正常工作:

implicit def repSucc[A <: Nat, B <: Nat](implicit 
    ev: A <:< Succ[B], 
    r: RepNat[B] 
): RepNat[A] = 
    new RepNat[A](r.value + 1) 

究其原因,我认为,这是 repSucc得到一个单一的实际类型参数A,并且需要计算该B。根据你的定义,它试图同时分配AB,因此B被有效分配到Nothing

这是Scala中类型推断的常见问题,通常的解决方案是将绑定的类型A <: M[B]移动到广义类型约束A <:< M[B]

另外,还要注意的隐含参数的顺序很重要:第一,编译器从A计算Bev: A <:< Succ[B],然后找到RepNat实施B,可能是递归。

相关问题