I have defined my own version of WriterT along with a function to unwrap it:
newtype WT w m a = WT (m a, w)
unWT :: (Monoid w, Monad m) => WT w m a -> (m a, w)
unWT (WT cmaw) = cmaw
Now I am trying to define the monad (WT w m), without success:
instance (Monoid w, Monad m) => Monad (WT w m) where
return x = WT (return x, mempty)
wtwma >>= fawtwmb = WT $ let (ma, w1) = unWT wtwma
(mb, w2) = unWT $ do a <- ma
fawtwmb a
in (mb, mappend w1 w2)
Error is located in the do-expression, at the point where I try to extract a from ma:
Expected type: WT w m a, Actual type: m a
I have tried a few variations, always with similar outcome. I am unable to define bind for this monad.
My main question is: if the monad is inside a couple, how do I extract its value?
Imagine the following computation:
tellLine :: WT String IO ()
tellLine = do
input <- WT (getLine, "")
WT (return (), input)
impossible :: String
impossible = snd (unWT tellLine)
If this works as "expected", we should get that impossible is the string that the user entered. However, we cannot do this outside of IO; such an impossible could not be a pure String as it is here. So it is not possible to yield a w that was recieved as the result of a computation in the monad.
Another possibility is simply to return the w that occurred before the first bind, so we don't have to depend on any monadic actions. Alas, one of the identity laws thwarts us.
return x >>= f = f x
Here we can see that "before the first bind" cannot be a meaningful concept, since there is a bind on the left but not on the right. So returning the w that occurs before the first bind will surely violate this monad law.
The only remaining possibility is for the w to always be mempty. But this does not work either, because of the other identity law.
m >>= return = m
so if m has a non-mempty value of w, the bind would annihilate it and violate this law.
This WT cannote be a monad transformer. There is a WriterT transfomer, but it is defined as m (a,w) which avoids these problems.
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