/ / `forever` Combinator avec type plus gentil - Scala

Combinateur `pour toujours 'avec type de parenté supérieur - scala

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 № 1

a 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.