/ Kombinátor "navždy" s vyšším typom - stupnica

"navždy" Kombinátor s vyšším druhom - scala

Snažím sa spustiť nasledujúci kombinátor z Funkčné programovanie v programe 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)
}
}

Ale to nie je kompilácia:

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

Chápem, že musím použiť F[_] pretože označuje typ vyššej triedy.

Napríklad som napísal a Monad[List] v predchádzajúcej kapitole tejto knihy:

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
}

UPRAVIŤ pridanie Monad a Functor kód

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]

Ako môžem vyriešiť vyššie uvedenú chybu kompilácie? Aký význam má F[_] ako typ AddlCombinators a Monad? Dá sa použiť všeobecný „druh vyššieho druhu“?

odpovede:

2 pre odpoveď č. 1

a flatMap (_ => t) je tu vinník.

Podľa zadaného kódu môžete použiť flatMap(a)(_ => t) aby som to skompiloval.

Rozhranie Monad nepridáva automaticky monadické operátory k žiadnemu parametrizovanému typu, pokiaľ nepoužívate implikácie.

F[_] je existenciálny typ, čo znamená, že F je typ, ktorý obsahuje nejaký iný typ, ktorý je ekvivalentný: trait F {type A}, Každý Monad je funktor a funktory môžu byť iba parametrizované typy, preto je potrebné parametrizovať Monad pomocou F[_], Inými slovami, rozhranie Monad / Functor môžu uspokojiť iba paratmeterizované typy. Typ parametrizovaný parametrom (* -> *) -> * je typ vyššej kategórie. F[_] je najmenej reštriktívny, teda najbežnejší typktoré môžete použiť tu. Prostredníctvom projekcií typu je možné urobiť ďalšie paramterizované typy tak, aby vyzerali ako F [_]. Napríklad na definovanie Monadu pre pravý neobjektívny typ, ktorý môžete použiť type FA = ({type l[a] = Either[L, a]})#l ako F[_], vidieť tu pre kompletný kód pre Monad for Either.