The non-termination is (probably) due to the fact that you can have uninterruptible threads in ghc.<br>If a thread never allocates it will never be preempted. :(<br><br> -- Lennart<br><br><div><span class="gmail_quote">On 7/24/07,
<b class="gmail_sendername">Dan Weston</b> <<a href="mailto:westondan@imageworks.com">westondan@imageworks.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I am trying to get my feet wet with Haskell threads with the following<br>problem, inspired by a recent post<br>(<a href="http://www.haskell.org/pipermail/haskell-cafe/2007-July/029408.html">http://www.haskell.org/pipermail/haskell-cafe/2007-July/029408.html
</a>)<br>saying that:<br><br> > Since there's no way to have a function be lazy in both arguments, the<br> > implicit convention is to make functions strict in the first arguments<br> > and, if applicable, lazy in the last arguments. In other words, the
<br> > convention is<br> ><br> > True || _|_ = True but not _|_ || True = True<br> ><br> > 1 + _|_ = Succ _|_ but not _|_ + 1 = Succ _|_<br> ><br> > Regards,<br> > apfelmus<br><br>Maybe not lazy in both arguments, but how about lazy in either argument?
<br><br>The idea is to fork a thread for each of the two functions, (||) and<br>flip (||), pick the winner, then kill off both threads. I can wrap this<br>up in a pure function using unsafePerformIO (given the proof obligation
<br>that the results of both threads will always be equal where both are<br>defined).<br><br>The code below seems to work, except for the following problems:<br><br>1) Commenting out the type annotation f :: Bool makes the program hang
<br>2) If I replace f = f by f = undefined, I get an annoying print of<br>"LazyOr: Prelude.undefined" before it returns the correct value.<br><br>Does anyone know why the type annotation is needed in #1, and/or how to
<br>suppress the error message in #2?<br><br>Dan Weston<br><br>-----------------------------------------------------------<br>import Control.Monad(when)<br>import Control.Concurrent(forkIO,killThread)<br>import Control.Concurrent.Chan
(newChan,readChan,writeChan,isEmptyChan)<br>import Foreign(unsafePerformIO)<br><br>f :: Bool<br>f = f<br><br>main = putStrLn . show $ lazyBinaryOp (||) f True<br><br>lazyBinaryOp p x y = unsafePerformIO $ do<br> c <- newChan
<br> p2 <- forkIO (lazyBinaryOpThread c p x y)<br> p1 <- forkIO (lazyBinaryOpThread c p y x)<br> z <- readChan c<br> killThread p1<br> killThread p2<br> return z<br><br> where<br><br> lazyBinaryOpThread c p x y = do
<br> case (p x y) of True -> writeChan c True<br> False -> writeChan c False<br><br>_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">
Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br></blockquote></div><br>