On the signature of >>= Monad operator

后端 未结 6 2322
粉色の甜心
粉色の甜心 2021-02-14 13:54

This is the signature of the well know >>= operator in Haskell

>>= :: Monad m => m a -> (a -> m b) -> m b

The question is why

6条回答
  •  滥情空心
    2021-02-14 14:46

    I think that J. Abrahamson's answer points to the right reason:

    Basically, (>>=) lets you sequence operations in such a way that latter operations can choose to behave differently based on earlier results. A more pure function like you ask for is available in the Functor typeclass and is derivable using (>>=), but if you were stuck with it alone you'd no longer be able to sequence operations at all.

    And let me show a simple counterexample against >>= :: Monad m => m a -> (a -> b) -> m b.

    It is clear that we want to have values bound to a context. And perhaps we will need to sequentially chain functions over such "context-ed values". (This is just one use case for Monads).

    Take Maybe simply as a case of "context-ed value".

    Then define a "fake" monad class:

    class Mokad m where  
         returk :: t -> m t  
         (>>==) :: m t1 -> (t1 -> t2) -> m t2
    

    Now let's try to have Maybe be an instance of Mokad

    instance Mokad Maybe where
             returk x = Just x
             Nothing >>== f = Nothing
             Just x >>== f = Just (f x) -- ????? always Just ?????
    

    The first problem appears: >>== is always returning Just _.

    Now let's try to chain functions over Maybe using >>== (we sequentially extract the values of three Maybes just to add them)

    chainK :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int
    chainK ma mb mc = md 
          where
            md = ma >>== \a -> mb >>== \b -> mc >>== \c -> returk $ a+b+c
    

    But, this code doesn't compile: md type is Maybe (Maybe (Maybe Int)) because every time >>== is used, it encapsulates the previous result into a Maybe box.

    And on the contrary >>= works fine:

    chainOK :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int
    chainOK ma mb mc = md 
          where
            md = ma >>= \a -> mb >>= \b -> mc >>= \c -> return (a+b+c)  
    

提交回复
热议问题