Suppose we have two monads, m
and m'
. Now, suppose we have variables,
-- in real problems, the restriction is some subclass MyMonad, so don't worry
-- if it's the case here that mx and f must essentially be pure.
mx :: Monad m'' => m'' a
f :: Monad m'' => a -> m'' b
Is there a way to create anything similar to the product m x m'
? I know this is possible with Arrows, but it seems more complicated (impossible?) for monads, especially when trying to write what mx >>= f
should do.
To see this, define
data ProdM a = ProdM (m a) (m' a)
instance Monad ProdM where
return x = ProdM (return x) (return x)
but now, when we define mx >>= f
, it's not clear which value from mx
to pass to f
,
(ProdM mx mx') >>= f
{- result 1 -} = mx >>= f
{- result 2 -} = mx' >>= f
I want (mx >>= f) :: ProdM
to be isomorphic to ((mx >>= f) :: m) x ((mx >>= f) :: m')
.
Monads do compose, but the result might not be a monad. In contrast, the composition of two applicatives is necessarily an applicative.
What is a Monad? 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.
Another way you can say "monads can be pure" is that Haskell distinguishes between creating a monadic computation and running the computation. Creating a monadic computation is pure and doesn't involve any side effects.
A monadic function is a function that produces a monadic value. ( Note that we said nothing about its input type) and. Functions of the form f :: a -> m b , where a is the type of the inner value of the monad. ( Call these classic monadic functions)
Yes, this type is a monad. The key is simply to pass both results to f
, and only keep the matching field from the result. That is, we keep the first element from the result of passing mx
's result, and the second element from the result of passing mx'
's result. The instance looks like this:
instance (Monad m, Monad m') => Monad (ProdM m m') where
return a = ProdM (return a) (return a)
ProdM mx mx' >>= f = ProdM (mx >>= fstProd . f) (mx' >>= sndProd . f)
where fstProd (ProdM my _) = my
sndProd (ProdM _ my') = my'
ProdM
is available in the monad-products package under the name Product
.
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