With monads, can a union be defined in terms of binding?

In Haskell, monads are defined using the return and bind functions, where return is of type a -> ma , and bind is of type ma -> (a -> mb) -> mb . It was previously indicated that monads can also be defined in terms of return and join, where join is a function of type m (ma) -> ma . Binding can be defined in terms of union, but is the opposite possible? Can a union be defined in terms of bind?

Without a connection, I have no idea what I would do if I ever get the monadic value “double wrapped”, m (ma) - none of the functor or monad operations “removes layers”, so to speak, If this is not possible , why does Haskell and many other monad implementations define them in terms of bind? This seems less useful than join-based definition.

+6
source share
3 answers

Maybe:

 join :: Monad m => m (ma) -> ma join m = (m >>= id) 

Note the complicated creation >>= :

 (>>=) :: mb -> (b -> mc) -> mc -- choosing b ~ ma , c ~ a (>>=) :: m (ma) -> (ma -> ma) -> ma 

therefore, we can choose the right id for the second argument.

+9
source

Yes, it is quite simple:

 join m = m >>= id 
+6
source

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) 
+3
source

All Articles