
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. 2. I don't recall anyone claiming it is shorter - the only claim was that it was simpler to think of (for some people) and 'nicer' from mathematical standpoint. Simplifying problem is common technique so I guess that defence of join is unharmed. Say - you want to prove linearity of function φ - you can either: 1. Prove aφ(x) = φ(ax) and φ(x) ⊕ φ(y) = φ(x + y) 2. Prove aφ(x) ⊕ bφ(y) = φ(ax + by) Which one do you choose? well it depends on φ and your skills. If φ is simple you and you have done it before you may prefer the 2. Otherwise you may prefer 1 even if it longer.
2011/1/9 Conal Elliott
* The familiarity advantage of (>>=) is a historical accident. I like to see the language improve over time, rather than accumulate accidents. I would be surprised if choosing ">>=" was an accident: it seems more likely that it was chosen because it matches a commonly occurring pattern in functional programs, and abstraction is all about giving names to common patterns.
Yes and no. Common pattern is function of form (read :: Read a => String -> a) - surprisingly it is not the one you define as it is too limited. (>>=) is probably better described as 'what happens' and functional programming is not about what happens but what people want to achieve (usually (>>=) but not always) or what people find easier to think about (quick survey of this thread point into direction of join). PS. As of simplifying. I have a feeling that the thread is: around 6 people with opinion (sorry if I've counted incorrectly): - Ok - sometimes (>>=) is simpler for implementation sometimes join so adding join would allow to choose simpler one or favourite 1 person with opinion - But (>>=) is great and noone is using join so why bother with join PPS. As of tutorials - somehow I don't recall anyone bothering with getting in deep of Read class on my Haskell course. Tutorial may not even mentioning it as class method and novice will not notice that the method existed