Haskell - Is effect order deterministic in case of Applicative?

后端 未结 3 1687
耶瑟儿~
耶瑟儿~ 2021-01-01 21:03

When executing the IO action defined by someFun <$> (a :: IO ()) <$> (b :: IO ()), is the execution of the a and b actions

相关标签:
3条回答
  • 2021-01-01 21:26

    Yes, the order is predefined by the Monad-Applicative correspondence. This is easy to see: The (*>) combinator needs to correspond to the (>>) combinator in a well-behaved Applicative instance for a monad, and its definition is:

    a *> b = liftA2 (const id) a b
    

    In other words, if b were executed before a, the Applicative instance would be ill-behaving.

    Edit: As a side note: This is not explicitly specified anywhere, but you can find many other similar correspondences like liftM2 = liftA2, etc.

    0 讨论(0)
  • 2021-01-01 21:33

    It's certainly deterministic, yes. It will always do the same thing for any specific instance. However, there's no inherent reason to choose left-to-right over right-to-left for the order of effects.

    However, from the documentation for Applicative:

    If f is also a Monad, it should satisfy pure = return and (<*>) = ap (which implies that pure and <*> satisfy the applicative functor laws).

    The definition of ap is this, from Control.Monad:

    ap :: (Monad m) => m (a -> b) -> m a -> m b
    ap =  liftM2 id
    

    And liftM2 is defined in the obvious way:

    liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
    

    What this means is that, for any functor that is a Monad as well as an Applicative, it is expected (by specification, since this can't be enforced in the code), that Applicative will work left-to-right, so that the do block in liftM2 does the same thing as liftA2 f x y = f <$> x <*> y.

    Because of the above, even for Applicative instances without a corresponding Monad, by convention the effects are usually ordered left-to-right as well.

    More broadly, because the structure of an Applicative computation is necessarily independent of the "effects", you can usually analyze the meaning of a program independently of how Applicative effects are sequenced. For example, if the instance for [] were changed to sequence right-to-left, any code using it would give the same results, just with the list elements in a different order.

    0 讨论(0)
  • 2021-01-01 21:38

    For the IO Applicative, this is certainly the case. But check out the async package for an example of an Applicative where in f <$> a <*> b the effects of a and b happen in parallel.

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