
Hi, Apologies for referring to this old thread... I rearranged the code a little bit while experimenting but retained the same behaviour: Prelude> let f = undefined :: Int -> IO Int Prelude> (f 3 >> f 3) `seq` 42 42 Prelude> (f 3) `seq` 42 *** Exception: Prelude.undefined I think this makes it a little simpler for me to see the issue here. Simply, 'undefined >> undefined' is a bit more defined than simply 'undefined'. Just like 'undefined:undefined' is at least a non-empty list; which can be matched by (_:_) for example. This explains the differing behaviour of the two seemingly equivalent actions above. So I think the above behaviour is more to do with how shallow seq is, as others have probably already shown (but much of the rest of the thread is beyond me). Prelude> undefined `seq` 5 *** Exception: Prelude.undefined Prelude> (undefined:undefined) `seq` 5 5 Aaron (relative newbie)
On 1/23/07, Brian Hulley
wrote: Brian Hulley wrote:
Brian Hulley wrote:
Yitzchak Gale wrote:
I wrote:
> Prelude> let f = undefined :: Int -> IO Int > Prelude> f `seq` 42 > *** Exception: Prelude.undefined > Prelude> ((>>= f) . return) `seq` 42 > 42 The monad laws say that (>>= f) . return must be identical to f.
I thought it was:
return x >>= f = f x
so here the lhs is saturated, so will hit _|_ when the action is executed just as the rhs will.
Ooops! But that does not mean the equation holds because for example
Prelude> (return 3 >>= f) `seq` 42 42 Prelude> (f 3) `seq` 42 *** Exception: Prelude.undefined
In the lhs you only hit _|_ when the composite (>>=) action is actually being executed whereas in the rhs you hit _|_ when computing the function which will return the action to execute so there is difference.
Brian. -- http://www.metamilk.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Aaron McDaid wrote:
Apologies for referring to this old thread...
At least for me, this is not old. It is still very much on my mind.
Simply, 'undefined >> undefined' is a bit more defined than simply 'undefined'. Just like 'undefined:undefined' is at least a non-empty list; which can be matched by (_:_) for example. This explains the differing behaviour of the two seemingly equivalent actions above.
I think you are correct. And that is the problem. As a simple Haskell programmer, I am starting from the fact that seq exists and works in a certain way. Given that reality, I want to look at what monads should look like and what strictness properties they should have. Well, even with seq around, Haskell types and functions still form a nice category - except you have to be careful to use strict composition instead of regular Haskell composition when viewing Haskell functions as morphisms in the category. So then what is a monad? There is one obvious extra requirement: Monad Strictness Law: (>>=) must be strict in its second argument. That law follows from the monad law: (>>= f) .! return = f when we take f = _|_ (and we make the assumption that our monad is not degenerate - return x /= _|_ for some x). Making (>>=) strict in the second argument would be a very minor change. That change would affect few, if any, existing Haskell programs. I am becoming convinced that this should be considered a bug in IO. Unfortunately, I don't think that fixing this bug will help much with other known monad strictness problems, such as the State/StateT strictness bug. Regards, Yitz
participants (2)
-
Aaron McDaid
-
Yitzchak Gale