One thing I noticed was that Tuple
does not have a Monad
instance.
Tuple does however have an Applicative
instance:
instance Monoid a => Applicative ((,) a)
Which already extremely heavily restricts what we can make the Monad
instance be.
Lets look at the type signature we would get for join:
instance Monoid a => Monad ((,) a)
join :: Monad m => m (m a) -> m a
join :: Monoid a => (a, (a, b)) -> (a, b)
We can also look at the Monad laws:
join $ f <$> pure x == f x
join $ f <$> (mempty, x) == f x
join (mempty, f x) == f x
join (mempty, (a, b)) == (a, b)
join $ pure <$> x = x
join $ pure <$> (a, b) = (a, b)
join (a, (mempty, b)) = (a, b)
At this point we know that combining mempty
and x
in either way results in x
. And the only type information we have about x
is that it is a Monoid
. So basically the only two implementations are:
join (a, (b, x)) = (a <> b, x)
and:
join (a, (b, x)) = (b <> a, x)
And the second one of those makes ap
and <*>
not the same.
So now we know that the only valid Monad
instance for ((,) a)
is:
instance Monoid a => Monad ((,) a) where
(a, c) >>= f = let (b, c') = f c in (a <> b, c')
So why is that not currently the case?
Well it seems like the answer to this question is that I just have to use ghc-8.0.1
, which does give Tuple
a Monad
instance. Credit to @Michael for pointing this out.
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