
On Sun, Jan 9, 2011 at 10:41 PM, Maciej Piechotka
On Sun, 2011-01-09 at 18:16 -0800, Iavor Diatchki wrote:
Hello, In my experience, defining monads in terms of "fmap" and "join" leads to code duplication. The examples we have seen in this thread---so far---are a bit misleading because they compare a partial implementation of a monad (join without fmap) with a complete implementation (bind). Here is an example of what I mean:
data SP a = PutChar Char (SP a) | GetChar (Char -> SP a) | Return a
fmapSP :: (a -> b) -> (SP a -> SP b) fmapSP f (PutChar c sp) = PutChar c (fmapSP f sp) fmapSP f (GetChar k) = GetChar (\c -> fmapSP f (k c)) fmapSP f (Return a) = Return (f a)
joinSP :: SP (SP a) -> SP a joinSP (PutChar c sp) = PutChar c (joinSP sp) joinSP (GetChar k) = GetChar (\c -> joinSP (k c)) joinSP (Return sp) = sp
bindSP :: (a -> SP b) -> (SP a -> SP b) bindSP f (PutChar c sp) = PutChar c (bindSP f sp) bindSP f (GetChar k) = GetChar (\c -> bindSP f (k c)) bindSP f (Return a) = f a
I chose this example because I think that it illustrates nicely how the three operators work, I hope that other readers find it useful.
Yes and no:
1. In monad transformers & co. you want weakened conditions on Functor and Applicative so you cannot reuse (>>=) in them - you end up with a function anyway.
Is this true? Applicative functors compose, so you shouldn't need to
use monad transformers. Of the common monad transformers, the only
ones where the Applicative instance can be defined in terms of the
underlying Applicative instance are Identity, Reader, and Writer, all
of which are equivalent to composition (that is, you don't gain
anything by using the transformer instead of composition).
--
Dave Menendez