Bind ( >>= ) really "removes the layer":
(>>=) :: Monad m => ma -> (a -> mb) -> mb
Intuitively, it "gets a from ma " and then passes it to the a -> mb function, and then returns a single mb result from the results.
Usually people say that for the function argument it is necessary to complete the output in m again, but this is not so. To output the function, it is necessary that something be completed in m , but no matter where the packaging came from.
In the case of the join implementation, we start with something called a double wrap: m (ma) . We can connect this to the signature for binding and immediately figure out the type of function that we could use when binding the double-wrapped value:
m (ma) -> (ma -> mb) -> mb
Now the function used here for the binding will get a value that is already wrapped in m . Therefore, we do not need to “rewind” anything; if we return it without changes, it will already be the correct type for the output. It’s effective that they "removed one layer of wraps" - and this works for any layer except the last.
So we just need to bind to id :
join = (>>= id)
source share