Intro to

Concurrent

Haskell

Sean Hagstrom

Intro to

Concurrent

Haskell

Haskell

Haskell

Pure

Typed

Lazy

-- module imports
import Control.Concurrent

-- function definition
add a b = a + b

-- function definition with type annotations
add :: Int -> Int -> Int
add a b = a + b

-- main of program
main :: IO ()
main = putStrLn "Hello"

-- main of program with more sugar
main :: IO ()
main = do
  putStrLn "Hello"
  putStrLn "World"

Haskell

Threads

Threads

Process

Thread #1

Thread #2

Haskell Threads

Green

Preemptive

import Control.Concurrent
import Control.Monad
import System.IO

sleep = threadDelay . (10^6 *)

main = do
  hSetBuffering stdout NoBuffering
  forkIO $ forever $ putChar 'A'
  forkIO $ forever $ putChar 'B'
  sleep 1
$ runhaskell threads.hs | tail -c 100


ABABABABABABABABABABABABABABABABABABABABABABABABAB
ABABABABABABABABABABABABABABABABABABABABABABABBBBB

Haskell

Threads

IORefs

IORefs

Mutable

IO Only

import Control.Concurrent
import Control.Monad
import Data.IORef

sleep = threadDelay . (10^6 *)

main = do
  counter <- newIORef 0

  forkIO $ forever $ do
    modifyIORef' counter (+1)
    sleep 1

  forever $ do
    sleep 1
    readIORef counter >>= putStr . show 
$ runhaskell iorefs.hs

2
3
4
5
5

Haskell

Threads

MVars

IORefs

MVars

Mutable

Locking

Fair

MVar

Value

Value

Value

Value

Value

Value

import Control.Concurrent
import Control.Concurrent.MVar

main = do
  mvar <- newEmptyMVar

  forkIO $ do
    putMVar mvar 'a'

  char <- takeMVar mvar
  print char

$ runhaskell mvars.hs

'a'
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Monad

sleep = threadDelay . (10^6 *)

main = do
  counter <- newMVar 0

  forkIO $ forever $ do
    count <- takeMVar counter
    sleep 1
    putMVar counter $! count + 1

  forever $ do
    withMVar counter (putStr . show)
1
2
3
4
5
$ runhaskell mvars-counter.hs

1
2
3
4
5

Channels

Haskell

Threads

MVars

IORefs

Channels

Buffered

Unbounded

Async

Channel

Read

Write

Stream

import Control.Concurrent
import Control.Concurrent.Chan
import Control.Monad

subscriber chan = do
  newChan <- dupChan chan
  forever $ do
    putChar =<< readChan newChan

main = do
  chan <- newChan
  forkIO $ subscriber chan
  forkIO $ subscriber chan
  writeChan chan 'a'
  writeChan chan 'b'
$ runhaskell channels.hs

a
a
b
b
import Control.Concurrent
import Control.Concurrent.Chan
import Control.Monad
import Data.IORef

sleep = threadDelay . (10^6 *)

publisher chan = do
  counter <- newIORef 0
  forever $ do
    count <- fmap (+1) $ readIORef counter
    writeChan chan count
    writeIORef counter count
    sleep 1 

main = do
  chan <- newChan
  forkIO $ publisher chan
  forever $ readChan chan >>= (putStr . show)
$ runhaskell channels-counter.hs

1
2
3
4
5

Channels

Haskell

Threads

MVars

IORefs

Channels

Async

STM

GHC 

More?

Concurrent Haskell

Resources

by Simon Marlow

Reliable Concurrency Without the Actor Model

by Andrew Rademacher

Parallel and Concurrent Programming in Haskell

by Simon Marlow

chimera.labs.oreilly.com/books/1230000000929

youtube.com/watch?v=8OQUH8q4sMM

www.infoq.com/presentations/Concurrent-Haskell

Beautiful Concurrency

Resources

by Simon Peyton Jones

Haskell Simple Concurrency

by @eightyeight

Haskell Wiki

github.com/eightyeight/haskell-simple-concurrency 

wiki.haskell.org

schoolofhaskell.com/school/advanced-haskell/beautiful-concurrency

Questions?

Intro to Concurrent Haskell

By Sean Hagstrom

Intro to Concurrent Haskell

A nice introduction to Concurrency in Haskell

  • 315