J'essaie de lancer le combinateur suivant depuis Programmation fonctionnelle en 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)
}
}
Mais ce n'est pas compiler:
[error] AddlCombinators.scala:7: value flatMap is not a member of type
parameter F[A]
[error] a flatMap (_ => t)
[error] ^
Ma compréhension est que je dois utiliser F[_]
comme il dénote un type plus gentil.
Par exemple, j'avais écrit un Monad[List]
dans un chapitre passé de ce livre:
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
}
MODIFIER Ajouter Monad
et 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]
Comment puis-je résoudre l'erreur de compilation ci-dessus? Aussi, quel est le sens de F[_]
comme type à AddlCombinators
et Monad
? Peut-on utiliser un "type plus élevé" en général?
Réponses:
2 pour la réponse № 1a flatMap (_ => t)
est le coupable ici.
Selon le code donné, vous pouvez utiliser flatMap(a)(_ => t)
pour le compiler.
Monad interface n’ajoute pas automatiquement d’opérateurs monadiques à un type paramétré sauf si vous utilisez des implicites
F[_]
est un type existentiel, ce qui signifie que F est un type qui contient un autre type, équivalent à: trait F {type A}
. Chaque monade est un functor et seuls les types paramétrés peuvent être des functors, vous devez donc paramétrer Monads avec F[_]
. En d'autres termes, seuls les types paramétrisés peuvent satisfaire l'interface Monad / Functor. Un type paramétré par un type paramétré (* -> *) -> *
est un type plus gentil. F[_]
est le type le moins restrictif, donc le plus généralcela peut être utilisé ici. D'autres types paramétrés peuvent ressembler à F [_] via des projections de type. Par exemple, pour définir une monade pour un type indifférent, vous pouvez utiliser type FA = ({type l[a] = Either[L, a]})#l
comme F[_]
. Voir ici pour le code complet pour Monad pour les deux.