By the title, I mean types like Monad m => m (m a)
.
When the structure of a monad is simple, I can easily think of a usage of such type:
[[a]]
, which is a multidimensional list
Maybe (Maybe a)
, which is a type adjoined by two error states
Either e (Either e a)
, which is like above, but with messages
Monoid m => (m,(m,a))
, which is a writer monad with two things to write over
r -> r -> a
, which is a reader monad with two things to read from
Identity (Identity a)
, which is still the identity monad
Complex (Complex a)
, which is a 2-by-2 matrix
But it goes haywire in my mind if I think about the following types:
ReadP (ReadP a)
? Why would it be useful when ReadP
isn't an instance of Read
?
ReadPrec (ReadPrec a)
? Like above?
Monad m => Kleisli m a (Kleisli m a b)
?
IO (IO a)
!? This must be useful. It just is too hard to think about it.
forall s. ST s (ST s a)
!? This should be like the above.
Is there a practical use for such types? Especially for the IO
one?
On the second thought, I might need to randomly pick an IO
action. That's an example of IO (IO a)
which focuses on inputs. What about one focusing on outputs?
monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems.
In short, monads are hard to explain because we've yet to identify anything in the human experience that corresponds to this useful abstraction. This is, in my opinion, comparable to quantum mechanics or relativity theory.
Monad is a simple and powerful design pattern for function composition that helps us to solve very common IT problems such as input/output, exception handling, parsing, concurrency and other. Application becomes less error prone.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
In some sense, a monad can be thought of as a functor in which layers can be collapsed.
If the Monad
class were defined more like the category-theory definition, it would look like
class Applicative m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
Using fmap
with a function of type a -> m b
results in a function of type m a -> m (m b)
. join
is used to eliminate one layer of monad from the result. Since that's a common thing to do, one might define a function that does it.
foo :: Monad m => (a -> m b) -> m a -> m b
foo f ma = join (fmap f ma)
If you look carefully, you'll recognize foo
as >>=
with its arguments flipped.
foo = flip (>>=)
Since >>=
is used more than join
would be, the typeclass definition is
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
and join
is defined as a separate function
join :: Monad m => m (m a) -> m a
join mma = mma >>= id
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With