
On Mon, 2011-01-10 at 19:01 -0500, David Menendez wrote:
On Sun, Jan 9, 2011 at 10:41 PM, Maciej Piechotka
wrote: 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).
1. Add MaybeT and ListT to 'the only ones'. 2. As of non-trivial Applicative see InterleaveT from last MonadReader (issue 17). Regards