Question

De une douce introduction à Haskell, il y a les lois monade suivantes. Quelqu'un peut-il expliquer intuitivement ce qu'ils veulent dire?

return a >>= k             = k a
m >>= return               = m
xs >>= return . f          = fmap f xs
m >>= (\x -> k x >>= h)    = (m >>= k) >>= h

Voici ma tentative d'explication:

  1. Nous nous attendons à la fonction de retour à envelopper a de sorte que sa nature monadique est trivial. Lorsque nous lier à une fonction, il n'y a pas d'effets monades, il devrait simplement passer a à la fonction.

  2. La sortie non emballé de m est passé à return que rewraps elle. La nature monadique reste le même. Il est donc le même que la monade d'origine.

  3. La valeur déballés est passée à f puis reconditionnés. La nature monadique reste le même. Ce comportement est prévu lorsque nous transformons une fonction normale en fonction monadique.

  4. Je n'ai pas une explication de cette loi. Cela ne dit que la monade doit être « presque associative » bien.

Était-ce utile?

La solution

Vos descriptions semblent assez bien. En général, les gens parlent de trois lois monade, que vous avez 1, 2 et 4. Votre troisième loi est légèrement différente, et je reviendrai plus tard.

Pour les trois lois monade, je trouve beaucoup plus facile d'obtenir une compréhension intuitive de ce qu'ils veulent dire quand ils sont re-écrit en utilisant la composition Kleisli:

-- defined in Control.Monad
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
mf >=> n = \x -> mf x >>= n

Maintenant, les lois peuvent être écrites comme:

1) return >=> mf = mf                  -- left identity
2) mf >=> return = mf                  -- right identity
4) (f >=> g) >=> h = f >=> (g >=> h)   -- associativity

1) Loi Identité gauche -. Retour d'une valeur ne change pas la valeur et ne fait rien dans la monade

2) Loi identité droit -. Retour d'une valeur ne change pas la valeur et ne fait rien dans la monade

4) associativité - composition monadique est associative (I comme la réponse de KennyTM pour cela)

Les deux lois d'identité disent essentiellement la même chose, mais ils sont tous les deux nécessaires parce que return doit avoir un comportement identité des deux côtés de l'opérateur de liaison.

Maintenant, pour la troisième loi. Cette loi dit essentiellement que les deux l'instance Functor et votre instance Monad se comportent de la même manière lors de la levée d'une fonction dans la monade, et que ni ne monadique quoi que ce soit. Si je ne me trompe pas, il est vrai que lorsqu'un obéisse monade les trois autres lois et l'instance Functor obéit aux lois de foncteurs, cette déclaration sera toujours vrai.

Beaucoup de cela vient de la Haskell Wiki . Typeclassopedia est une bonne référence aussi.

Autres conseils

désaccords Pas avec les autres réponses, mais il pourrait aider à penser aux lois monade comme décrivant en fait deux ensembles de propriétés. Comme le dit Jean, la troisième loi dont vous parlez est un peu différent, mais voici comment les autres peuvent être séparés divisée:

Fonctions qui vous lient à une Compose de monade comme fonctions régulières.

Comme dans la réponse de John, ce qu'on appelle une flèche Kleisli pour une monade est une fonction de type a -> m b. Pensez à return comme id et (<=<) comme (.), et les lois monade sont les traductions de celles-ci:

  1. id . f équivaut à f
  2. f . id équivaut à f
  3. (f . g) . h équivaut à f . (g . h)

Séquences d'effets monades append comme des listes.

Pour la plupart, vous pouvez penser à la structure monadique supplémentaire en tant que séquence de comportements supplémentaires associés à une valeur monadique; par exemple. Maybe étant « abandonner » pour Nothing et « continuez » pour Just. La combinaison de deux actions monades alors concaténer essentiellement les séquences de comportements qu'ils détenaient.

Dans ce sens, return est à nouveau une identité - l'action nulle, semblable à une liste vide des comportements - et (>=>) est concaténation. Ainsi, les lois monade sont des traductions de celles-ci:

  1. [] ++ xs équivaut à xs
  2. xs ++ [] équivaut à xs
  3. (xs ++ ys) ++ zs équivaut à xs ++ (ys ++ zs)

Ces trois lois décrivent un modèle ridiculement commun qui Haskell exprimer ne peut malheureusement pas tout à fait en toute généralité. Si vous êtes intéressé, Control.Category donne une généralisation de « choses qui ressemblent à la composition de fonctions », alors que ce dernier Data.Monoid généralise le cas où aucun paramètre de type sont impliqués.

En termes de notation do, règle 4 signifie que nous pouvons ajouter un bloc do supplémentaire pour le groupe une séquence d'opérations monadiques.

    do                          do
                                  y <- do
      x <- m                             x <- m
      y <- k x          <=>              k x
      h y                         h y

Cela permet à des fonctions qui renvoient une valeur monadique fonctionne correctement.

Les trois premières lois disent que « retour » enveloppe seulement une valeur et ne fait rien d'autre. Ainsi, vous pouvez éliminer les appels « de retour » sans changer la sémantique.

La dernière loi est associativité pour se lier. Cela signifie que vous prenez quelque chose comme:

do
   x <- foo
   bar x
   z <- baz

et la transformer en

do
   do
      x <- foo
      bar x
   z <- baz

sans changer le sens. Bien sûr, vous ne voudriez pas faire exactement, mais vous voudrez peut-être mettre la clause intérieure « faire » dans un « si » et que vous voulez qu'il signifie la même chose quand le « si » est vrai.

Parfois monades ne suivent pas exactement ces lois, en particulier quand une sorte de valeur inférieure se produit. C'est OK tant que son documenté, « moralement correct » (à savoir les lois sont respectées pour les valeurs non-bas, ou les résultats sont considérés comme équivalents d'une autre manière).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top