[Haskell-cafe] Do monads imply laziness?
stefanor at cox.net
Sat Apr 14 11:22:04 EDT 2007
On Sat, Apr 14, 2007 at 10:56:44AM -0400, Brian Hurt wrote:
> This is probably an off-topic question, but I can't think of a better
> forum to ask it: does the existance of monads imply laziness in a
> language, at least at the monadic level?
> Consider the following: a purely functional, eagerly evaluated programming
> language, that uses monads to encapsulate the awkward squad. In this
> programming language, a program generates an IO monad whose encapsulating
> computation performs side effecting affections- it writes to stdout, say.
> But this generated monad never has it's value evaluated- the monad is
> tossed away uninspected. Does the side effect happen? If the answer is
> at least potientially "no", then monads are lazily evaluated, and thus
> monads imply laziness (at least at the monadic level). On the other hand,
> if the answer is "yes", then monads do not imply laziness.
First off, having monadic IO does not mean that there are side effects
at ANY level, consider:
data IOTree = PutChar Char IOTree | GetChar (Char -> IOTree)
type IO = Cont IOTree
putChar ch = Cont $ \x -> PutChar ch (x ())
getChar = Cont $ \x -> GetChar x
No effects, monadic IO!
Secondly, all real languages delay evaluation on a function, so that
IOTree will not be constructed all at once, but incrementally as input
arrives. If you want it more incremental in a strict language, it
would be simple:
data IOTree = PutChar Char (() -> IOTree) | GetChar (Char -> IOTree)
Just for fun, here is code for monadic IO in the pure subset of O'Caml
(a strict functional language). All side effects are in 'interp'.
type iotree = Stop | Put of char * (unit -> iotree) | Get of (char -> iotree);;
type 'a io = ('a -> iotree) -> iotree;;
let putChar ch cont = Put (ch, cont) ;;
let getChar cont = Get cont ;;
let exit cont = Stop ;;
let (>>=) act aft cont = act (fun v -> aft v cont) ;;
let return vl cont = cont vl ;;
let rec interp0 tree = match tree with
Stop -> ()
| Put (ch, ct) -> print_char ch ; interp0 (ct ())
| Get ct -> interp0 (ct (input_char stdin)) ;;
let interp act = interp0 (act (fun x -> Stop)) ;;
More information about the Haskell-Cafe