我正在尝试打印皮亚诺数字,如下所示:
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]])))
最佳答案
递归隐式确实有效。以下定义适用于 _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
从那。根据您的定义,它会尝试分配 A
和B
同时,因此B
被有效分配给Nothing
。
这是 Scala 中类型推断的常见问题,通常的解决方案是移动类型绑定(bind) A <: M[B]
到广义类型约束A <:< M[B]
。
另外,请注意隐式参数的顺序很重要:编译器首先计算 B
来自A
与 ev: A <:< Succ[B]
,然后找到 RepNat
实现B
,可能是递归的。
关于scala - 有没有办法对类型进行递归隐式定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40690370/