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ď č. 1a 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.