首页 文章

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

提问于
浏览
1

我正在尝试从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 添加 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 的类型是什么意思?可以使用"higher kinded type"一般吗?

1 回答

  • 2

    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 .

相关问题