What are the internals of a bind operation in a monad?

All about Monads writes:

“The >>= function is known as “bind” because it binds the value in a monad container to the first argument of a function. By adding logic to the binding function, a monad can implement a specific strategy for combining computations in the monad.”

What does it mean to “add logic to the binding function” ? Where can I find a good example on this, with an explanation? How much freedom do we have on a bind function when it should obey the monadic laws?

Consider >>= implementation for Maybe. The logic is what to do with the different possible constructors of the type: how to get a value and how proceed with (or without) it.

1 Like

Monads are just a type class (from Haskell’s POV). Type classes are roughtly equivalent to interfaces in Java, Abstract Classes in python or Traits in Scala/Rust.

Since they are just an interface, you can implement instances with arbitrary logic. It is expected that implementations follow some reasonable properties (called monad laws)

Notice that there is nothing magical nor special with monads. They are a plain old interface, so don’t over mistify them. The reason they are prominent in Haskell and not so much in other langs, is because the Haskell type system has higher-kinded polymorphism (afaik, most mainstream languages do not support this) and ad-hoc syntax to work with them. Notice that monads can be implemented in other languages, but higher-kinded polymorphism make them easy to define

You should go to hackage and look for monad instances. For example the basic types Maybe and [] do implement monad instances with different logic. You can see the implementations clicking on # source link under instances

I assume, @gbuday, that “binding function” refers to the function on the right side of >>=. So where m represents the monad constructor, here is an illustration:

(m a) >>= (\x -> ...)

The “binding function” is (\x -> ...). This is where a gets bound to x. (I added unnecessary parentheses for the sake of absolute clarity.)

The “logic [added] to the binding function” is what you would use to replace the three dots. You can do pretty much anything you want with x in this part of the function. The only rule is that in the end the function (\x -> ...) must return an instance of the monad m. That is, it must return something in the same “container”. (That’s required by the type of >>=.)

I am not an expert on Haskell, and it may be that there are technical refinements needed to make what I said fully correct, but I think it is a good entry point to an answer to what you were asking. I thought it might be worthwhile to give an answer from my point of view, even though I am not an expert, because I think I may be close to the mindset that led to the question. (Or it could be that I am just telling you a lot of things you already know, and that I misunderstood the question.)

Think to understand bind you need to consider the syntactic sugar of the do syntax which so much Haskell code is written as:

monad :: _ () <- what monad?
monad = do 
    result1 <- action1
    result2 <- action2
    return ()

monad' = action1 >>= \result1 -> 
    action2 >>= \result2 -> 
        return ()

The functionality of this depends on ‘the logic of the binding function’. I.E. What monad are we sequencing these actions in? IO?, Maybe?, State? Specifically, what happens if the bind fails to produce a result? Each monad has a MonadFail instance to determine that.