Exploring this material: Lens over tea I've encountered an interesting (simple at first) point:
ex3 :: (a, b) -> (b, a)
ex3 = do
a <- fst
b <- snd
return (b, a)
Everything's fine, but what type of monad does this function use (since we have a do-block inside). After a few attempts I arrived to this conclusion:
ex2 :: ReaderT (a, b) ((,) b) a
ex2 = ReaderT $ do
a <- fst
b <- snd
return (b, a)
ex3 :: (a, b) -> (b, a)
ex3 = runReaderT ex2
So, we have ReaderT that uses inner monad ((,) b). Interestingly enough - I got not enough satisfaction with this and decided to rewrite ex2 not using do-notation. This is what I got:
ex2 :: Monoid b => ReaderT (a, b) ((,) b) a
ex2 = ReaderT $
\pair -> return (fst pair) >>=
\a -> return (snd pair) >>=
\b -> (b, a)
or even:
ex2 :: Monoid b => ReaderT (a, b) ((,) b) a
ex2 = ReaderT $
\pair -> (mempty, fst pair) >>=
\a -> (mempty, snd pair) >>=
\b -> (b, a)
Both variants require b to have a Monoid type restriction. The question is: can I write this functions with (>>=) only and without using a Monoid restriction - like we have with do-notation variant? Apparently we do the same with or without do-notation. Maybe the even difference, that we have to construct monads at every step in the second and thirst fuctions and this requires us to state that "b" should be a monoid - some monoid. And in the first case we just extract our values from some monad - not constructing them. Can anybody explain am I thinking in the right direction?
Thank you!!