我正在尝试从Functional Programming in Scala运行以下组合器:
trait AddlCombinators[F[_]] extends Monad[F[_]] {
def forever[A, B](a: F[A]): F[B] = {
lazy val t: F[B] = forever(a)
a flatMap (_ => t)
}
}
但它没有编译:
[error] AddlCombinators.scala:7: value flatMap is not a member of type
parameter F[A]
[error] a flatMap (_ => t)
[error] ^
我的理解是我需要使用 F[_]
,因为它表示更高的kinded类型 .
例如,我在本书的前一章写了一篇 Monad[List]
:
object ListMonad extends Monad[List] {
def unit[A](a: => A): List[A] = List(a)
def flatMap[A,B](ma: List[A])(f: A => List[B]): List[B] =
ma.map(x => f(x)).flatten
}
EDIT 添加 Monad
和 Functor
代码
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Functor[F] {
def unit[A](a: => A): F[A]
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
如何解决上述编译时错误?另外, F[_]
作为 AddlCombinators
和 Monad
的类型是什么意思?可以使用"higher kinded type"一般吗?
1 回答
a flatMap (_ => t)
是罪魁祸首 .根据给出的代码,您可以使用
flatMap(a)(_ => t)
进行编译 .除非使用含义,否则Monad接口不会自动将monadic运算符添加到任何参数化类型 .
F[_]
是一个存在类型,这意味着F是一个包含其他类型的类型,相当于:trait F {type A}
. 每个Monad都是一个Functor,只有参数化类型可以是Functors,这就是你需要用F[_]
参数化Monads的原因 . 换句话说,只有paratmeterized类型可以满足Monad / Functor接口 . 由参数化类型(* -> *) -> *
参数化的类型是更高的kinded类型 .F[_]
是限制性最小的,因此这里可以使用最常用的类型 . 其他参数化类型可以通过类型投影看起来像F [_] . 例如,要为右偏置的Either类型定义Monad,可以使用type FA = ({type l[a] = Either[L, a]})#l
作为F[_]
. 有关Monad for Either的完整代码,请参阅here .