I'm just trying to get monads, so bear with me if I ask a bad question, but...
If monads only require:
(a -> M a)
, where M is the monadic type constructor, and(M a -> (a -> M b) -> M b)
, which is the bind operation (which I understand as mapping a monad onto a non-monadic to monadic value function)
...doesn't this mean that:
(M a -> a)
and(M (M a) -> M a)
are not implicitly required?
Won't this usually cause a problem?
Suppose we have a set of functions, S, which all have the type
(x -> y)
, where x and y are arbitrary types.Now, suppose I program using a set of monadic functions M, where their types are
x -> M y
.
Doesn't this mean that once I turn a type into M y
, I can't use any of the (x -> y)
functions? Or, can I assume that I can do (M x -> (x -> y) -> (y -> M y) -> M y)
?
Furthermore, don't we usually want to extract the original type when programming? When switching between something, like async a -> a
or maybe a -> a
... Isn't that a common operation? I can definitely see the case where somebody wants to optimize a monad out if they see it as negligible (e.g. a logging monad).
Additionally, what about layered monads without flattening? I understand that lists can be seen as monads where restricting flattening is a clear and logical choice, but what about the hypothetical case of async (async a)
monadic values where async
has no flatten function? Does bind only imply one layer of "monadic reduction" where we can often assume that (M a -> (a -> M a) -> M a)
can often be seen as (M a -> (M a -> a) -> (a -> M a) -> M a)
, and (M M a -> (a -> M a) -> M a or M M a)
may not work? Is there a true difference between flattening and non-flattening monads?