[Haskell-cafe] Lazy in either argument?

Dan Weston westondan at imageworks.com
Tue Jul 24 00:50:41 EDT 2007

I am trying to get my feet wet with Haskell threads with the following 
problem, inspired by a recent post 
saying that:

 > Since there's no way to have a function be lazy in both arguments, the
 > implicit convention is to make functions strict in the first arguments
 > and, if applicable, lazy in the last arguments. In other words, the
 > convention is
 >   True || _|_ = True   but not  _|_ || True = True
 >   1 + _|_ = Succ _|_   but not  _|_ + 1 = Succ _|_
 > Regards,
 > apfelmus

Maybe not lazy in both arguments, but how about lazy in either argument?

The idea is to fork a thread for each of the two functions, (||) and 
flip (||), pick the winner, then kill off both threads. I can wrap this 
up in a pure function using unsafePerformIO (given the proof obligation 
that the results of both threads will always be equal where both are 

The code below seems to work, except for the following problems:

1) Commenting out the type annotation f :: Bool makes the program hang
2) If I replace f = f by f = undefined, I get an annoying print of 
"LazyOr: Prelude.undefined" before it returns the correct value.

Does anyone know why the type annotation is needed in #1, and/or how to 
suppress the error message in #2?

Dan Weston

import Control.Monad(when)
import Control.Concurrent(forkIO,killThread)
import Control.Concurrent.Chan(newChan,readChan,writeChan,isEmptyChan)
import Foreign(unsafePerformIO)

f :: Bool
f = f

main = putStrLn . show $ lazyBinaryOp (||) f True

lazyBinaryOp p x y = unsafePerformIO $ do
     c  <- newChan
     p2 <- forkIO (lazyBinaryOpThread c p x y)
     p1 <- forkIO (lazyBinaryOpThread c p y x)
     z  <- readChan c
     killThread p1
     killThread p2
     return z


     lazyBinaryOpThread c p x y = do
       case (p x y) of True  -> writeChan c True
                       False -> writeChan c False

More information about the Haskell-Cafe mailing list