
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. Thanks, Brian

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)) ;; -------------------------- Stefan

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.
Thanks, Brian
Firstly, this question is not off-topic. Next, strictness and purity have nothing to do with monads. Finally, monadic values -represent- actions, they aren't the actions themselves. If you throw away a string representing some action that you were going to pass to an interpreter, the action it represents never happens, but this has nothing to do with laziness. Monadic IO in Haskell can be understood very much like that. The value of main gets passed to an IO interpreter, and all the work on the Haskell side is just building expressions for that interpreter (and thus it is now easy to see why this preserves purity). Laziness is not involved at all (except, as one person found out on c.l.f a long time ago, (>>) is less useful in a strict language than in a pure one, e.g. repeatM_ m = m >> repeatM_ m doesn't do anything in a strict language).
participants (3)
-
Brian Hurt
-
Derek Elkins
-
Stefan O'Rear