简体   繁体   中英

`forever` Combinator with Higher Kinded Type

I'm trying to run the following combinator from 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)
  }
}

But it's not compiling:

[error] AddlCombinators.scala:7: value flatMap is not a member of type 
      parameter F[A]
[error]     a flatMap (_ => t)
[error]       ^

My understanding is that I need to use F[_] as it denotes a higher kinded type.

For example, I had written a Monad[List] in a past chapter of this book:

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 Adding Monad and Functor code

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]

How can I resolve the above compile-time error? Also, what is the meaning of F[_] as the type to AddlCombinators and Monad ? Can a general "higher kinded type" be used?

a flatMap (_ => t) is the culprit here.

As per the code given, you can use flatMap(a)(_ => t) to get it compiling.

Monad interface does not automatically add monadic operators to any parameterised type unless you use implicits.

F[_] is an existential type which means that F is a type which contains some other type, equivalent to: trait F {type A} . Every Monad is a Functor, and only parameterised types can be Functors, which is why you need to parameterize Monads with F[_] . Put another way, only paratmeterized types can satisfy Monad/Functor interface. A type parameterized by a parameterized type (* -> *) -> * is a higher kinded type. F[_] is the least restrictive, hence most general type that can be used here. Other paramterized types can be made to look like F[_] via type projections. For example, to define a Monad for a right biased Either type, you can use type FA = ({type l[a] = Either[L, a]})#l as F[_] . See here for complete code for Monad for Either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM