Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining bind for home-made monad transformer

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?

like image 660
Marco Faustinelli Avatar asked Jan 28 '26 05:01

Marco Faustinelli


1 Answers

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.

like image 144
luqui Avatar answered Jan 31 '26 02:01

luqui



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!