Haskell Monad bind operator confusion

后端 未结 3 1071
滥情空心
滥情空心 2021-01-30 16:53

Okay, so I am not a Haskell programmer, but I am absolutely intrigued by a lot of the ideas behind Haskell and am looking into learning it. But I\'m stuck at square one: I can\'

3条回答
  •  囚心锁ツ
    2021-01-30 17:20

    Allow me to tear down your beliefs about Monads. I sincerely hope you realize that I am not trying to be rude; I'm simply trying to avoid mincing words.

    A Monad's purpose is to take a function with different input and output types and to make it composable. It does this by wrapping the input and output types with a single monadic type.

    Not exactly. When you start a sentence with "A Monad's purpose", you're already on the wrong foot. Monads don't necessarily have a "purpose". Monad is simply an abstraction, a classification which applies to certain types and not to others. The purpose of the Monad abstraction is simply that, abstraction.

    A Monad consists of two interrelated functions: bind and unit.

    Yes and no. The combination of bind and unit are sufficient to define a Monad, but the combination of join, fmap, and unit is equally sufficient. The latter is, in fact, the way that Monads are typically described in Category Theory.

    Bind takes a non-composable function f and returns a new function g that accepts the monadic type as input and returns the monadic type.

    Again, not exactly. A monadic function f :: a -> m b is perfectly composable, with certain types. I can post-compose it with a function g :: m b -> c to get g . f :: a -> c, or I can pre-compose it with a function h :: c -> a to get f . h :: c -> m b.

    But you got the second part absolutely right: (>>= f) :: m a -> m b. As others have noted, Haskell's bind function takes the arguments in the opposite order.

    g is composable.

    Well, yes. If g :: m a -> m b, then you can pre-compose it with a function f :: c -> m a to get g . f :: c -> m b, or you can post-compose it with a function h :: m b -> c to get h . g :: m a -> c. Note that c could be of the form m v where m is a Monad. I suppose when you say "composable" you mean to say "you can compose arbitrarily long chains of functions of this form", which is sort of true.

    The unit function takes an argument of the type that f expected, and wraps it in the monadic type.

    A roundabout way of saying it, but yes, that's about right.

    This [the result of applying unit to some value] can then be passed to g, or to any composition of functions like g.

    Again, yes. Although it is generally not idiomatic Haskell to call unit (or in Haskell, return) and then pass that to (>>= f).

    -- instead of
    return x >>= f >>= g
    -- simply go with
    f x >>= g
    
    -- instead of
    \x -> return x >>= f >>= g
    -- simply go with
    f >=> g
    -- or
    g <=< f
    

提交回复
热议问题