
Le 26 mars 2014 21:19, Valentin Robert
Ci-dessous une intuition guidée par les types pour identifier une différence entre les foncteurs applicatifs et les monades qui a été mentionée auparavant par Alp.
La composition de foncteurs applicatif a pour type: c a -> c (a -> b) -> c b La composition de monades a pour type: c a -> (a -> c b) -> c b
(J'ai renommé les variables f et m en c, et réordonné les paramètres pour simplifier mon explication)
Dans les deux cas, on souhaite applique uniformément une sorte de fonction (le second paramètre) sur une valeur en contexte (le premier paramètre).
Cependant, le type donné à la fonction lui confère un potentiel différent dans chaque cas: - pour Applicative, la fonction qui reçoit un a n'a pas la possibilité d'altérer son contexte, car la fonction est dans le contexte: c (a -> b) - pour Monad, la fonction qui reçoit un a se charge de construire le contexte pour son résultat: a -> c b
Du coup, dans Applicative, la valeur de a peut seulement influencer la valeur de b, mais pas la structure du contexte c. Alors que dans Monad, la valeur de a peut influencer à la fois la valeur de b et la structure du contexte c dans lequel b est placé.
---
Dans le cas des listes :
(<*>) :: [a -> b] -> [a] -> [b] -- j'ai remis les paramètres dans l'ordre d'Haskell pour la suite de mon email (>>=) :: [a] -> (a -> [b]) -> [b]
Pour (fl <*> xl), quelles que soient les valeurs dans xl, la liste résultante aura autant d'éléments que le produit du nombre d'éléments de fl et xl. Les fonctions contenues dans fl peuvent contrôler les valeurs dans la liste finale, mais pas la structure de la liste finale.
Pour (xl >>= fl), les fonctions peuvent également affecter la structure résultante.
[1,2,3] >>= (\a -> if a == 1 then [] else [a+1, a+2])
Ici, j'ai le droit de regarder la valeur, et de modifier la structure du contexte produit (par exemple, je produis une liste vide quand la valeur est 1, et une liste à deux éléments autrement).
---
Dans la monade IO, c'est ce qui te permet de choisir quelles actions faire en fonction du résultat produit par les actions précédentes.
(<*>) :: IO (a -> b) -> IO a -> IO b (>>=) :: IO a -> (a -> IO b) -> IO b
iof <*> ioa -- quelle que soit la valeur produite par ioa, on applique la fonction dans iof ioa >>= (\a -> ....) -- ici, dans les ... tu peux regarder a, et effectuer différentes actions, ce qui est impossible avec Applicative
---
Corrigez-moi si je dis des bêtises... je suis malade et fatigué ! :-)
- Valentin
Ça me paraît plus clair, pour être sur : * une Applicative me permet de réunir inconditionnellement deux expression au sein d'un même contexte (une sorte de write only) * une Monade me permet de lire la valeur d'un contexte et dans recréer un à ma guise, comme je le souhaite (une sorte de read, drop, create) Merci.