我正在尝试减少此代码(scalaz 7.0.x,scala 2.10.x):
type Error[+A] = \/[String, A]
type Result[+A] = OptionT[Error, A]
Run Code Online (Sandbox Code Playgroud)
进入这个:
type Result[+A] = OptionT[({ type ?[+?] = String \/ ? })#?, A]
Run Code Online (Sandbox Code Playgroud)
我得到错误"找不到scalaz.Applicative [Main.Result]类型的证据参数的隐含值":
val result: Result[Int] = 42.point[Result]
Run Code Online (Sandbox Code Playgroud)
为什么简化代码看起来不像scalac的第一个例子?
lambda 类型的隐式解析似乎被破坏了。显然,编译器首先对类型进行脱糖处理,然后对类型参数的数量进行不匹配。
一个“简化”的例子:
定义一个单子和两个特征。One类似于Either。Two类似于EitherT
trait Monad[F[_]]
trait One[A, B]
object One {
implicit def m[A]: Monad[({ type T[x] = One[A, x] })#T] = ???
}
trait Two[F[_], A]
object Two {
implicit def m[F[_]]: Monad[({ type T[x] = Two[F, x] })#T] = ???
}
Run Code Online (Sandbox Code Playgroud)
定义一个类型别名和一个案例类来部分应用One作为String它的第一个参数。案例类版本可以用作解决方法。
type OneX[A] = One[String, A]
case class OneY[A](value: OneX[A])
object OneY {
implicit def m(implicit ev: Monad[OneX]): Monad[OneY] = ???
}
Run Code Online (Sandbox Code Playgroud)
所有“简单”类型的隐式解析都有效。
implicitly[Monad[OneX]]
implicitly[Monad[({ type T[x] = One[String, x] })#T]]
implicitly[Monad[OneY]]
Run Code Online (Sandbox Code Playgroud)
定义几个部分适用的类型别名Two
type TwoX[A] = Two[OneX, A]
type TwoY[A] = Two[({ type T[x] = One[String, x] })#T, A]
type TwoZ[A] = Two[OneY, A]
Run Code Online (Sandbox Code Playgroud)
在这里我们看到使用 lambda 类型的失败。
implicitly[Monad[TwoX]]
implicitly[Monad[TwoY]] // fails
implicitly[Monad[TwoZ]]
Run Code Online (Sandbox Code Playgroud)
在这里我们看到所有使用类型别名的 lambda 类型都会失败。只有实际引用具有单个参数的稳定类型的类型才会成功。
implicitly[Monad[({ type T[x] = Two[OneX, x] })#T]] // fails
implicitly[Monad[({ type T[x] = Two[OneY, x] })#T]]
implicitly[Monad[({ type T[x] = Two[({ type T[x] = One[String, x] })#T, x] })#T]] //fails
Run Code Online (Sandbox Code Playgroud)
我对编译器的了解相当有限,这可能与@TravisBrown 指出的错误有关。
| 归档时间: |
|
| 查看次数: |
1309 次 |
| 最近记录: |