Dirt-simple multi-threading in Haskell

I am a completely newbie to Haskell, and I wanted to find out about concurrency. After the usual rounds of being completely baffled as to why my program won’t compile, a managed to come up with a very simple multi-threaded program:

import Control.Concurrent
import Control.Concurrent.Async

calc x = do 
  d<- threadDelay (round (x * 1000000.0)) -- x seconds 
  return (10.0 + x) 

main = do 
  let m1 = map calc [3.5, 3.2, 3.6] 
  t3 <- mapM async m1 
  t4 <- mapM wait t3 
  print(t4)


It’s pretty much a case of “what could be simpler?”. I have a function calc which I want to apply concurrently to some list, in this case [3.5, 3.2, 3.6]. In this particular case, my function calc takes a float as an argument, x. It delays for x seconds, and returns x+10 as a result. It then collect the results in the order of the original list, and print them out.

If I ‘runhaskell’ on the above program, I obtain the expected result: [13.5,13.2,13.6] Running ‘time runhaskell foo.hs’ gives me the following output:

real 0m3.940s
user 0m0.302s
sys 0m0.056s

So it is clearly running the threads concurrently, rather than sequentially.

I am very happy with the simplicity of this code. It abstracts things so beautifully.

My next goal is to use it to perform concurrent downloads of urls. ‘calc’ will become something like ‘getUrl’, and the list will be replaced by a list of urls.

An easy-to-overlook part of the code is the line: let m1 = map calc [3.5, 3.2, 3.6] The really cool bit is that Haskell is LAZY, so it will only try to perform the mapping as it needs to. If the mapping had been eager, as in most languages, then the program would have taken over 10 seconds to execute (being the cumulative delay time of 10.3). Although Haskell is not the easiest language to get to grips with, it has some really really cool stuff that makes for some very terse code. I am very encouraged by my experiments with Haskell.

/projects/repos/cerbo/ssah/multi.hs

Update 09-Mar-2015: Apparently the good folks writing the Haskell libraries already anticipated my requirement in the form of mapConcurrently .

Update 25-Mar-2015: There is also a discussion of this post over on Reddit.

Advertisements

About mcturra2000

Computer programmer living in Scotland.
This entry was posted in haskell. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s