[Shootout-list] Haskell killer prodcons implementation - fair?
Einar Karttunen
ekarttun@cs.helsinki.fi
Sun, 3 Oct 2004 18:20:56 +0300
This is a MIME-formatted message. If you see this text it means that your
E-mail software does not support MIME-formatted messages.
--=_courier-2877-1096816860-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
On 03.10 09:29, Raymond Racine wrote:
> The Haskell version (I believe) simply returns the inputted n value for
> the consumed counter then reads n-1 produced i's, and returns the nth
> mVar value for the produced counter. This is at odds with the pseudo
> code.
Attached is a version which does use the counters.
It is even faster than the current one ;)
If you want I can commit something like this. It contains two ways of
doing the counter one for producer and other for consumer to show it
can be done easily.
Of course you can argue that replacing counters with recursion is evil
and should be banned, but then again please consider that haskell has
no looping constructs.
> Therefore, IMHO, it is fair that languages which support side effecting
> I/O concisely and elegantly with statements or ref cells should not be
> punished because they do have to do loops or recursive calls to perform
> what Haskell is doing with a simple list comprehension. Dealing with
> those counters with two additional mVars (or alternative means) will
> clutter up the current solution but it is an aspect of Haskell
> programming (dealing with side effecting I/O) that should not be hand
> waved away.
uhm why should the counters be shared with other threads? That sounds
kind of counterproductive. All the other languages are using simple
variables which are just updated, so using recursion is the most
natural way in haskell.
Consider the C fragment:
for(int i; i < n; i++) foo;
Now one can write in Haskell
loop 0 = return ()
loop n = foo >> loop (n-1)
loop i n | i == n = return ()
| True = foo >> loop (i+1) n
loop n = replicateM_ n loop
loop n = mapM_ (const foo) [1..n]
All of these are more or like equivalent, and I think avoiding the
explicit loops is good because of notational beauty, although it is
usually slightly slower than actually writing the loop.
- Einar Karttunen
--=_courier-2877-1096816860-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="ab.hs"
-- $Id: prodcons.ghc.html,v 1.6 2004/10/03 00:44:58 bfulgham Exp $
-- http://shootout.alioth.debian.org/
-- by JP Bernardy, optimized by Einar Karttunen
import Control.Concurrent
import System
producer n m mv | n == m = return m
| True = putMVar mv n >> producer (n+1) m mv
consumer 0 m mv = return m
consumer n m mv = takeMVar mv >> consumer (n-1) m mv
main = do [a] <- getArgs
let n = read a :: Int
mvar <- newEmptyMVar
ret <- newEmptyMVar
forkIO (producer 0 n mvar >>= putMVar ret)
m <- consumer n n mvar
r <- takeMVar ret
putStrLn (show r ++ " " ++ show m)
--=_courier-2877-1096816860-0001-2--