Posts Tagged 'haskell'

Simple Multi-Threaded Application in Haskell

Haskell has a powerful concurrency library which is surprisingly easy to use. The Control.Concurrent library is shipped with the standard installation of ghc and provides everything needed to get started.

As a small test I want to write a programme which reads numbers from stdin, spawns a new process to calculate the Fibonacci number for each input on a different CPU and prints the result to stdout.

First we need a function which is called when spawning a new process, which should calculate the result and print it to the console. In my case this is a simple IO Monad, which gets a MVar as it’s first argument. The function will wait for input from the MVar and then call the Fibonacci function.

This MVar can be thought of as a synchronised box where a thread can store a value and another thread can read from it. So MVars are just the poor men’s message channel which can hold one value at the time only. Of course there are also real channels in Haskell which act like the message queues in Scala or Erlang, see Control.Concurrent.Chan for more informations.

printResult mvar =  do
	value <- takeMVar mvar
	print $ "fib(" ++ show value ++ ")=" ++ show (fib value)

fib 0 = 0
fib 1 = 1
fib n =  fib (n - 1) + fib (n - 2)

Now we need to read the input from stdin, create a MVar object and invoke the printResult function. The cool thing about Haskell is the forkIO function which is really convenient. It takes an arbitrary IO expr and invokes it in a new thread:

import Control.Monad -- needed for "forever"
import System.Exit     -- needed for exitSuccess

main = forever $ do
	line <- getLine
	when (line == "quit") exitSuccess
	mvar <- newEmptyMVar
	forkIO $ printResult mvar
	putMVar mvar (read line :: Integer)

Now we have to compile our programme with the “-threaded” flag:

ghc -threaded fib.hs -o fib

The RTS allows us now to define the number of processors the application runs on with the -Nnum flag. If I want to use three processors for parallelisation I can run the programme simply with:

./fib +RTS -N4