具有更高金属类型的`forever`组合器

时间:2014-02-19 01:21:50

标签: scala

我正在尝试从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
}

编辑添加MonadFunctor代码

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[_]作为AddlCombinatorsMonad的类型的含义是什么?可以使用一般的“更高级的”吗?

1 个答案:

答案 0 :(得分:2)

a flatMap (_ => t)是罪魁祸首。

根据给出的代码,您可以使用flatMap(a)(_ => t)进行编译。

Monad接口不会自动将monadic运算符添加到任何参数化类型,除非您使用implicits。

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