30 votes

L'ascenseurM peut-il être différent de l'ascenseurA ?

Selon la Typeclassopedia (entre autres sources), Applicative se situe logiquement entre Monad y Pointed (et donc Functor ) dans la hiérarchie des classes de types, de sorte que nous aurions idéalement quelque chose comme ceci si le prélude Haskell était écrit aujourd'hui :

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Functor f => Pointed f where
    pure :: a -> f a

class Pointed f => Applicative f where
    (<*>) :: f (a -> b) -> f a -> f b

class Applicative m => Monad m where
    -- either the traditional bind operation
    (>>=) :: (m a) -> (a -> m b) -> m b
    -- or the join operation, which together with fmap is enough
    join :: m (m a) -> m a
    -- or both with mutual default definitions
    f >>= x = join ((fmap f) x)
    join x = x >>= id
    -- with return replaced by the inherited pure
    -- ignoring fail for the purposes of discussion

(où ces définitions par défaut ont été retapées par moi à partir de la base de données de l'UE). explication à Wikipedia (les erreurs étant de mon fait, mais s'il y a des erreurs, c'est au moins en principe possible).

Comme les bibliothèques sont actuellement définies, nous avons :

liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM ::       (Monad m) => (a -> b) -> m a -> m b

et :

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap    ::       (Monad m) => m (a -> b) -> m a -> m b

Notez la similitude entre ces types au sein de chaque paire.

Ma question est la suivante : est-ce que liftM (à distinguer de liftA ) et ap (à distinguer de <*> ), simplement le résultat de la réalité historique que Monad n'a pas été conçu avec Pointed y Applicative en tête ? Ou sont-elles d'une autre manière comportementale (potentiellement, pour certains aspects légaux Monad ) distinctes des versions qui ne requièrent qu'une Applicative contexte ?

S'ils sont distincts, pourriez-vous fournir un ensemble de définitions simples (obéir aux lois exigées de Monad , Applicative , Pointed y Functor décrites dans la Typeclassopedia et ailleurs mais non appliquées par le système de types) pour lesquelles liftA y liftM se comportent-ils différemment ?

Sinon, si elles ne sont pas distinctes, pourriez-vous prouver leur équivalence en utilisant ces mêmes lois comme prémisses ?

24voto

Apocalisp Points 22526

liftA , liftM , fmap y . devrait sont toutes de la même fonction, et elles debe être s'ils satisfont à la loi du foncteur :

fmap id = id

Cependant, cela n'est pas vérifié par Haskell.

Maintenant pour l'Applicatif. C'est possible pour ap y <*> d'être distincts pour certains foncteurs simplement parce qu'il pourrait y avoir plus d'une implémentation qui satisfasse les types et les lois. Par exemple, List a plus d'une implémentation possible Applicative instance. Vous pourriez déclarer un applicatif comme suit :

instance Applicative [] where
  (f:fs) <*> (x:xs) = f x : fs <*> xs
  _      <*> _      = []
  pure              = repeat

En ap serait toujours définie comme liftM2 id qui est le Applicative qui est fournie gratuitement avec chaque Monad . Mais ici vous avez un exemple d'un constructeur de type ayant plus d'un type. Applicative instance, qui satisfont toutes deux aux lois. Mais si vos monades et vos foncteurs applicatifs ne sont pas d'accord, il est considéré comme bon d'avoir des types différents pour eux. Par exemple, le Applicative ci-dessus ne concorde pas avec la monade de [] donc vous devriez vraiment dire newtype ZipList a = ZipList [a] et ensuite créer la nouvelle instance pour ZipList au lieu de [] .

8voto

Martijn Points 3955

Ils peut diffèrent, mais ils ne devrait pas .

Ils peuvent différer parce qu'ils peuvent avoir des implémentations différentes : l'un est défini dans une instance Applicative tandis que l'autre est définie dans un instance Monad . Mais si elles diffèrent effectivement, alors je dirais que le programmeur qui a écrit ces instances a écrit un code trompeur.

Vous avez raison : les fonctions existent comme elles le font pour des raisons historiques. Les gens ont des idées bien arrêtées sur la façon dont les choses auraient dû être.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X