What advantage does Monad give us over an Applicative?

后端 未结 8 556
心在旅途
心在旅途 2020-12-02 11:16

I\'ve read this article, but didn\'t understand last section.

The author says that Monad gives us context sensitivity, but it\'s possible to achieve the same result

相关标签:
8条回答
  • 2020-12-02 12:04

    Now that ApplicativeDo extension become pretty common thing, the difference between Monad and Applicative can be illustrated using simple code snippet.

    With Monad you can do

    do
       r1 <- act1
       if r1
            then act2
            else act3
    

    but having only Applicative do-block, you can't use if on things you've pulled out with <-.

    0 讨论(0)
  • 2020-12-02 12:06

    On the other hand, here's a a practical example of the Applicative/Monad divide where Applicatives have an advantage: error handling! We clearly have a Monad implementation of Either that carries along errors, but it always terminates early.

    Left e1 >> Left e2    ===   Left e1
    

    You can think of this as an effect of intermingling values and contexts. Since (>>=) will try to pass the result of the Either e a value to a function like a -> Either e b, it must fail immediately if the input Either is Left.

    Applicatives only pass their values to the final pure computation after running all of the effects. This means they can delay accessing the values for longer and we can write this.

    data AllErrors e a = Error e | Pure a deriving (Functor)
    
    instance Monoid e => Applicative (AllErrors e) where
      pure = Pure
      (Pure f) <*> (Pure x) = Pure (f x)
      (Error e) <*> (Pure _) = Error e
      (Pure _) <*> (Error e) = Error e
      -- This is the non-Monadic case
      (Error e1) <*> (Error e2) = Error (e1 <> e2)
    

    It's impossible to write a Monad instance for AllErrors such that ap matches (<*>) because (<*>) takes advantage of running both the first and second contexts before using any values in order to get both errors and (<>) them together. Monadic (>>=) and (join) can only access contexts interwoven with their values. That's why Either's Applicative instance is left-biased, so that it can also have a harmonious Monad instance.

    > Left "a" <*> Left "b"
    Left 'a'
    
    > Error "a" <*> Error "b"
    Error "ab"
    
    0 讨论(0)
提交回复
热议问题