Why should Applicative be a superclass of Monad?

前端 未结 4 1793
礼貌的吻别
礼貌的吻别 2020-12-04 15:32

Given:

Applicative m, Monad m => mf :: m (a -> b), ma :: m a

it seems to be considered a law that:

mf <*> ma ==         


        
4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-04 16:15

    and in my own (perhaps mistaken) intuition, given pure f <*> ma <*> mb, there needn't be any predetermined sequencing since none of the values depend on each other.

    The values don't, but the effects do. (<*>) :: t (a -> b) -> t a -> t b means that you have to somehow combine the effects of the arguments in order to get the overall effects. Whether the combination will be commutative or not depends on how the instance is defined. For example, the instance for Maybe is commutative, while the default, "cross join" instance for lists isn't. Therefore, there are cases in which you can't avoid imposing some order.

    What are the laws, if any, relating Monad and Applicative?

    While it is fair to say that pure === return and (<*>) === ap (quoting Control.Applicative) aren't laws in the strong sense that e.g. the monad laws are so, they help keeping the instances unsurprising. Given that every Monad gives rise to an instance of Applicative (actually two instances, as you point out), it is natural that the actual instance of Applicative matches what Monad gives us. As for the left-to-right convention, following the order of ap and liftM2 (which already existed back when Applicative was introduced, and which mirror the order imposed by (>>=)) was a sensible decision. (Note that, if we ignored for a moment how much (>>=) matters in practice, the opposite choice would be defensible as well, as it would make (<*>) and (=<<), which have analogous types, sequence effects in the same order.)

    Does GHC or any other tool perform code transformations that assume/require this law to be true?

    That sounds very unlikely given that Applicative isn't even a superclass of Monad(yet). These "laws", however, allow readers of the code to make the transformations, which matters just as much.

    N.B.: If you need to reverse the sequencing of effects in an Applicative instance, there is Control.Applicative.Backwards, as Gabriel Gonzalez has pointed out. Also, (<**>) flips the arguments but still sequences effects from left to right, so it can also be used to reverse sequencing. Similarly, (<*) is not flip (*>), as both sequence effects from left to right.

提交回复
热议问题