On Sun, Jun 24, 2012 at 2:48 AM, Chris Dornan
<chris@chrisdornan.com> wrote:
> > To move between functional and monadic code you have
> > to completely rewrite the code procedurally
> It's false. do-notation is completely optional. It merely makes it
> easier to extract multiple values from monadic actions, instead
> of the basic "one value per step" bind provides. Using join
> and (>>=) is just as easy as do-notation, once you understand the idiom.
Odersky's point (and mine) was about moving between monadic and functional
code,
not eliminating a do notation (which is indeed a fairly trivial syntactic
device). To take
a fake and absurd example, there is a world of difference between
add:: Double -> Double-> IO Double
and the stock addition operator. (Perhaps you need to be very careful about
exceptions.) If you structure your program so that certain kinds of
arithmetic has
to be done monadically then everything that uses these operations must be
written
quite differently from how it would be with simple arithmetic operations.
I sort of see where you're coming from. But I'm having a hard time seeing how this "complaint" would work with respect to Maybe and the other pure monads. In other words, I suspect the problem you're describing is particular to IO and IO-like monads.
If a function isn't total, it is entirely natural to use "Maybe" to encapsulate the potential for undefinedness. I would be extremely hesitant to call
mAdd :: Int -> Int -> Maybe Int
"monadic" unless it was actually using a monadic interface to Maybe. Indeed, I would call it "pure" and "functional". Similarly for:
(++) :: [a] -> [a] -> [a]
The result types are monadic insofar as they have a free type variable, but they are also entirely pure and functional.
You can argue that well it's just in the types -- you pays your money and
takes you
choice. (Viz., if your function works with effects then it should be
expressed in its type.)
Yes, this. If you need a list, use a list. If you need simple undefinedness, use Maybe, etc.
But then this becomes the price of doing everything in a strong functional
framework. To take one counter example, the Standard ML combines functional
programming and effects without forcing this reification on the programmer.
I don't know SML. How is our list "monadic" and theirs not? In particular, how is Haskell "forcing" the reification while SML does not?