Can liftM differ from liftA?

前端 未结 2 1264
醉话见心
醉话见心 2021-02-01 03:21

According to the Typeclassopedia (among other sources), Applicative logically belongs between Monad and Pointed (and thus Functor

相关标签:
2条回答
  • 2021-02-01 03:34

    They can differ, but they shouldn't.

    They can differ because they can have different implementations: one is defined in an instance Applicative while the other is defined in an instance Monad. But if they indeed differ, then I'd say the programmer who wrote those instances wrote misleading code.

    You are right: the functions exist as they do for historical reasons. People have strong ideas about how things should have been.

    0 讨论(0)
  • 2021-02-01 03:46

    liftA, liftM, fmap, and . should all be the same function, and they must be if they satisfy the functor law:

    fmap id = id
    

    However, this is not checked by Haskell.

    Now for Applicative. It's possible for ap and <*> to be distinct for some functors simply because there could be more than one implementation that satisfies the types and the laws. For example, List has more than one possible Applicative instance. You could declare an applicative as follows:

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

    The ap function would still be defined as liftM2 id, which is the Applicative instance that comes for free with every Monad. But here you have an example of a type constructor having more than one Applicative instance, both of which satisfy the laws. But if your monads and your applicative functors disagree, it's considered good form to have different types for them. For example, the Applicative instance above does not agree with the monad for [], so you should really say newtype ZipList a = ZipList [a] and then make the new instance for ZipList instead of [].

    0 讨论(0)
提交回复
热议问题