An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction...

106
An Introduction To Communicating Haskell Processes (CHP) Neil Brown School of Computing University of Kent UK 15 March 2010

Transcript of An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction...

Page 1: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

An Introduction ToCommunicating Haskell Processes

(CHP)

Neil Brown

School of ComputingUniversity of Kent

UK

15 March 2010

Page 2: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

What is CHP?

Communicating Haskell Processes:

Imperativesynchronous message-passingconcurrencylibrary for Haskell.

Page 3: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrency versus Parallelism

Concurrency

Using a different style ofprogramming

Parallelism

Getting performance fromparallel hardware

Page 4: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrency versus Parallelism

Concurrency

Using a different style ofprogramming

Parallelism

Getting performance fromparallel hardware

. . . not mutually exclusive!

Page 5: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (1/2)

data CHP a = ...instance Monad CHP where ...

Page 6: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (1/2)

data CHP a = ...instance Monad CHP where ...

instance MonadIO CHP whereliftIO :: IO a -> CHP a

runCHP :: CHP a -> IO a

Page 7: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (1/2)

data CHP a = ...instance Monad CHP where ...

instance MonadIO CHP whereliftIO :: IO a -> CHP a

runCHP :: CHP a -> IO a

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Basic API (1/2)

CHP is really a small layer of monad transformers on top of IO; henceyou can lift IO actions up into the CHP monad. CHP uses STM forimplementation.

Page 8: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (2/2)

runParallel :: [CHP a] -> CHP [a](<|*|>) :: CHP a -> CHP b -> CHP ()

Page 9: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (2/2)

runParallel :: [CHP a] -> CHP [a](<|*|>) :: CHP a -> CHP b -> CHP ()

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Basic API (2/2)

runParallel runs all the given actions in parallel and waits for them allto complete before returning the results. The <|*|> operator doesthis with two actions, discarding the results.

Page 10: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (2/2)

runParallel :: [CHP a] -> CHP [a](<|*|>) :: CHP a -> CHP b -> CHP ()

newChannelWR :: CHP (Chanout a, Chanin a)writeChannel :: Chanout a -> a -> CHP ()readChannel :: Chanin a -> CHP a

Page 11: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Basic API (2/2)

runParallel :: [CHP a] -> CHP [a](<|*|>) :: CHP a -> CHP b -> CHP ()

newChannelWR :: CHP (Chanout a, Chanin a)writeChannel :: Chanout a -> a -> CHP ()readChannel :: Chanin a -> CHP a

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Basic API (2/2)

We distinguish between the two ends of the channels in the typesystem to make it clear which process is writing to a channel andwhich is reading from it (and to prevent associated mistakes). Notethat the names are from the point of view of a process: Chanout isthe outgoing end on which a process will output; Chanin is theincoming end on which a process will input.

Page 12: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Identity Process

idP :: Chanin a -> Chanout a -> CHP ()

Page 13: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Identity Process

idP :: Chanin a -> Chanout a -> CHP ()

id

Page 14: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Identity Process

idP :: Chanin a -> Chanout a -> CHP ()

id

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Common Processes – The Identity Process

Processes in CHP lend themselves very well to being diagrammed,as you can see here. The identity process takes an incoming channelof some type a (the lilac hole on the left for an incoming arrow-head)and an outgoing channel of the same type (the lilac hold on the rightfor an outgoing arrow-head) and then is a complete CHP process.

Page 15: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Identity Process

idP :: Chanin a -> Chanout a -> CHP ()idP input output= forever (readChannel input >>= writeChannel output)

id

Page 16: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Identity Process

idP :: Chanin a -> Chanout a -> CHP ()idP input output= forever (readChannel input >>= writeChannel output)

id

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Common Processes – The Identity Process

The identity process has very simple code; it just forwards valuesfrom its incoming channel to its outgoing channel continually.

Page 17: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

Page 18: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

Page 19: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Identity Process Pipeline

I use the red stars here to indicate which channel a process iscurrently attempting to communicate on; all the processes begin byattempting to read from their input channels. The following diagramsshow what happens as various values are sent into and read from thepipeline; you can see that composing together these simpleprocesses gives a process pipeline.

Page 20: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

4148

Page 21: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

4148

Page 22: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

4148

Page 23: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

4148

Page 24: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

41482061

Page 25: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

idididid

41482061

Page 26: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

197idididid

414820613825

Page 27: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

197idididid

20613825

Page 28: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

197idididid

20613825

Page 29: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process Pipeline

197idididid

20613825

Page 30: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo :: Int -> Chanin a -> Chanout a -> CHP ()

Page 31: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo 1 input output = idP input output

Page 32: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo 1 input output = idP input outputfifo n input output= do (midOutput, midInput) <- newChannelWR

idP input midOutput <|*|> fifo (n-1) midInput output

Page 33: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo 1 input output = idP input outputfifo n input output= do (midOutput, midInput) <- newChannelWR

idP input midOutput <|*|> fifo (n-1) midInput output

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Identity Process (FIFO) Pipeline

You can see that we can specify the FIFO pipeline compositionally, ascomes naturally in functional programming. The pipeline of size 1 is asingle identity process, while the pipeline of size N is created byjoining (using a channel) one identity process on to the front of aFIFO pipeline of size N − 1.

Page 34: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

Page 35: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

Page 36: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

Page 37: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Identity Process (FIFO) Pipeline

We can capture this idea of composing one process next to another(that we saw in the previous slide) in an operator. The diagram showsthe processes we want to compose (it’s very easy on the diagram tosee how the processes will join together), and the next slide providesthe code. The composition operator is actually more general (morepolymorphic) than I’m showing here; I’ll come back to this later in theslides.

Page 38: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

(<=>) p q input output = do (w, r ) <- newChannelWRp input w <|*|> q r output

Page 39: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

(<=>) p q input output = do (w, r ) <- newChannelWRp input w <|*|> q r output

pipelineConnect :: [Chanin a -> Chanout a -> CHP ()]-> Chanin a -> Chanout a -> CHP ()

pipelineConnect = foldr1 (<=>)

Page 40: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

(<=>) :: (Chanin a -> Chanout b -> CHP ())-> (Chanin b -> Chanout c -> CHP ())-> (Chanin a -> Chanout c -> CHP ())

(<=>) p q input output = do (w, r ) <- newChannelWRp input w <|*|> q r output

pipelineConnect :: [Chanin a -> Chanout a -> CHP ()]-> Chanin a -> Chanout a -> CHP ()

pipelineConnect = foldr1 (<=>)2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Identity Process (FIFO) Pipeline

Once we have this composition operator, we can compose a pipelineof processes by just using the operator with a list fold. So thiscomposition fits very nicely with existing functional programmingpatterns.

Page 41: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo n = pipelineConnect (replicate n idP)

Page 42: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

idididid

fifo

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo n = pipelineConnect (replicate n idP)

Page 43: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

fifo

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo n = pipelineConnect (replicate n idP)

Page 44: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Identity Process (FIFO) Pipeline

fifo

fifo :: Int -> Chanin a -> Chanout a -> CHP ()fifo n = pipelineConnect (replicate n idP)

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Identity Process (FIFO) Pipeline

We can now code up the FIFO pipeline quite easily. The diagramsillustrate that we have now boxed up this component into its ownprocess, and the internal concurrency and channels are totally hiddenfrom the outside; it has become a black box. We can easily substitutethe inner workings of FIFO to use a data structure rather than all theconcurrent processes, and its interface (type and behaviour) wouldremain the same.

Page 45: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Map Process

mapP :: (a -> b) -> Chanin a -> Chanout b -> CHP ()mapP f input output= forever (readChannel input >>= writeChannel output . f)

Also: filter, replicate, scanl, tail, etc.

Page 46: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Common Processes – The Map Process

mapP :: (a -> b) -> Chanin a -> Chanout b -> CHP ()mapP f input output= forever (readChannel input >>= writeChannel output . f)

Also: filter, replicate, scanl, tail, etc.

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Common Processes – The Map Process

The identity process isn’t that useful; the map process here is themore general case and applies a function to the values passingthrough. Note that most of the list-processing functions in Haskell canhave CHP equivalents (effectively doing stream-processing).

Page 47: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example

Page 48: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example

Use several worker threads to test URLs using cURL.

Page 49: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Shared Channels

Shared channels allow multiple processes to access thereading and/or writing end of a channel.

claim :: Shared c a -> (c a -> CHP b) -> CHP be.g. claim :: Shared Chanin Int -> (Chanin Int -> CHP Int) -> CHP Int

claim input readChannel

Page 50: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example – cURL

data Details = Details { url :: String, user :: String, passwd :: String}

checkResponse :: Details -> IO (Maybe String)checkResponse d= responseError (user d) <$> curlGetResponse_ (url d)

[ CurlHttpAuth [HttpAuthAny], CurlUserPwd $ user d ++ ":" ++ passwd d]

Page 51: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example – cURL

runCHP_ $ do(resSend, resRecv) <- newChannelWR

printResultscheckResponse

checkResponse

checkResponse

Page 52: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example – cURL

runCHP_ $ do(resSend, resRecv) <- newChannelWRrunParallel_ $printResults resRecv :map (claim resSend . writeValue

<=< liftIO . checkResponse)details

printResultscheckResponse

checkResponse

checkResponse

Page 53: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Example – cURL

runCHP_ $ do(resSend, resRecv) <- newChannelWRrunParallel_ $printResults resRecv :map (claim resSend . writeValue

<=< liftIO . checkResponse)details

printResults :: Chanin (Maybe String)-> CHP ()

printResults c= replicateM_ (length details )

(readChannel c >>= liftIO . printResult )

printResultscheckResponse

checkResponse

checkResponse

Page 54: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Dynamically-Generated Work

getNextDetail printResultcheckResponse

checkResponse

checkResponse

Page 55: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Dynamically-Generated Work

getNextDetail :: IO Detail

genIO :: IO a -> Chanout a -> CHP ()genIO gen output = forever ( liftIO gen >>= writeChannel output)

getNextDetail printResultcheckResponse

checkResponse

checkResponse

Page 56: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Parallel Workers

manyIO :: Int -> (a -> IO b) -> Shared Chanin a -> Shared Chanout b -> CHP ()manyIO n worker input output= runParallel_ . replicate n . forever $

claim input readChannel>>= liftIO . worker>>= claim output . writeValue

getNextDetail printResultcheckResponse

checkResponse

checkResponse

Page 57: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Putting It Together

getNextDetail printResultcheckResponse

checkResponse

checkResponse

pipelineConnectComplete’(genIO getNextDetails)(manyIO checkAuthResponse)printResult

Page 58: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Pipeline With Feedback

dynFilter spotBad printResultcheckResponsegetNextDetail

checkResponse

checkResponse

Page 59: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Pipeline With Feedback

dynFilter spotBad printResultcheckResponsegetNextDetail

checkResponse

checkResponse

do (feedbackSend, feedbackRecv) <- newChannelWRpipelineConnectComplete’

(genIO getNextDetails)( dynFilter feedbackRecv <=> manyIO checkAuthResponse

<=> spotBad feedbackSend)printResult

Page 60: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Pipeline With Feedback

dynFilter spotBad printResultcheckResponsegetNextDetail

checkResponse

checkResponse

do (feedbackSend, feedbackRecv) <- newChannelWRpipelineConnectComplete’

(genIO getNextDetails)( dynFilter feedbackRecv <=> manyIO checkAuthResponse

<=> spotBad feedbackSend)printResult

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Pipeline With Feedback

It was pointed out during the code that there is a mistake in thedesign of this system; I should have inserted a buffer processbetween spotBad and dynFilter to avoid the possibility of deadlock.

Page 61: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

A Dynamically-Changing Filter

dynFilter :: Eq a => Chanin a -> Chanin a -> Chanout a -> CHP ()dynFilter filtInput input output = dynFilter ’ []

wheredynFilter ’ xs = (readChannel filtInput >>= dynFilter’ . (: xs))

<-> (do x <- readChannel inputunless (x ‘elem‘ xs) (writeChannel output x)dynFilter ’ xs)

dynFilter

filtInput

input output

Page 62: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

A Dynamically-Changing Filter

dynFilter :: Eq a => Chanin a -> Chanin a -> Chanout a -> CHP ()dynFilter filtInput input output = dynFilter ’ []

wheredynFilter ’ xs = (readChannel filtInput >>= dynFilter’ . (: xs))

<-> (do x <- readChannel inputunless (x ‘elem‘ xs) (writeChannel output x)dynFilter ’ xs)

dynFilter

filtInput

input output

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

A Dynamically-Changing Filter

This process uses the choice operator, <->, to choose betweenreading from the filtInput channel and the input channel. Note thatthe choice is between the leading event of each block only (the tworeads).

Page 63: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Altered Pipeline

getNextDetail printResultcheckResponse

checkResponse

checkResponse

Page 64: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Altered Pipeline

dynFilter spotBad printResultcheckResponsegetNextDetail

checkResponse

checkResponse

Page 65: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Altered Pipeline

dynFilter spotBad printResultcheckResponsegetNextDetail

checkResponse

checkResponse20

10-0

3-16

An Introduction ToCommunicating Haskell Processes(CHP)

Altered Pipeline

Note how, to change the behaviour of our system, we did not have toalter the behaviour of the existing system, but instead added morecomponents that added the functionality that we wanted.

Page 66: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Pull Architectures/Laziness

dynFilter spotBad printResultcheckResponsegetNextDetails

checkResponse

checkResponse

Page 67: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Pull Architectures/Laziness

dynFilter spotBad printResultcheckResponsegetNextDetails

checkResponse

checkResponse20

10-0

3-16

An Introduction ToCommunicating Haskell Processes(CHP)

Pull Architectures/Laziness

If we imagine boxing up the whole left-hand side of this system, wecan view it as something to pull data from (via the right-hand-mostchannel). Once all the processes on the left are waiting to output, nofurther work will be done until a value is read from the end, at whichpoint the next value will be calculated. So this is a pull-architecture,and has a rough analogue to laziness; work will only be done ondemand.

Page 68: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination

How do you shut down a process network?

1

Page 69: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

Page 70: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

1

Page 71: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

2

Page 72: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

3

Page 73: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

4

Page 74: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

5

Page 75: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Concurrent Termination: Poison

5

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Concurrent Termination: Poison

There is a good in-depth explanation of poison on my blog that coversit better than I could here in the notes:http://chplib.wordpress.com/2009/09/30/

poison-concurrent-termination/.

Page 76: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Poison

class Poisonable a wherepoison :: a -> CHP ()

instance Poisonable (Chanin a) whereinstance Poisonable (Chanout a) where

onPoisonRethrow :: CHP a -> CHP b -> CHP a

p input output = blah ‘onPoisonRethrow‘ (poison input >> poison output)

Page 77: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Communicating Sequential Processes

A process calculus developed by Hoare and Roscoe; booksfreely available online.

c!x → P writeChannel c x >>pc?x → P(x) readChannel c >>=pP || Q p <|*|>q

id(in, out) = in?x → out !x → id(in, out) idP

Page 78: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Communicating Sequential Processes

A process calculus developed by Hoare and Roscoe; booksfreely available online.

c!x → P writeChannel c x >>pc?x → P(x) readChannel c >>=pP || Q p <|*|>q

id(in, out) = in?x → out !x → id(in, out) idP

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Communicating Sequential Processes

I have a short introduction to CSP (with links to the books) on myblog: http://chplib.wordpress.com/2009/11/16/an-introduction-to-communicating-sequential-processes/

Page 79: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Testing and Tracing

Page 80: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Testing and Tracing

mostFreqWord = arr makeLower >>> arr words >>> modewhere

makeLower = map toLower

Page 81: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Testing and Tracing

mostFreqWord = arr makeLower >>> arr words >>> modewhere

makeLower = map toLower

mode = arr group >>> arr maxByLength >>> arr headwhere

maxByLength = maximumBy (comparing length)

Page 82: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Testing and Tracing

headmaxByLengthgroupwordsmakeLower

mostFreqWord = arr makeLower >>> arr words >>> modewhere

makeLower = map toLower

mode = arr group >>> arr maxByLength >>> arr headwhere

maxByLength = maximumBy (comparing length)

Page 83: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Testing and Tracing

headmaxByLengthgroupwordsmakeLower

testFreqWord = testCHPInOut (const (== "the")) (runPipelineLabelmostFreqWord)

"The quick brown fox jumps over the lazy dog"

main :: IO ()main = runTestTT testFreqWord >> return ()

Page 84: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Test Failure – Trace

headmaxByLengthgroupwordsmakeLower

### Failure:testCHP Failure; trace: < _c4,

makeLower->words."the quick brown fox jumps over the lazy dog",words->group.["the","quick","brown","fox",

"jumps","over","the","lazy","dog"],group->maxByLength.[["the"],["quick"],["brown"],["fox"],

["jumps"],["over"],["the"],["lazy"],["dog"]],maxByLength->head.["dog"],_c5 >

Cases: 1 Tried: 1 Errors: 0 Failures: 1

Page 85: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Test Failure – Trace

headmaxByLengthgroupwordsmakeLower

### Failure:testCHP Failure; trace: < _c4,

makeLower->words."the quick brown fox jumps over the lazy dog",words->group.["the","quick","brown","fox",

"jumps","over","the","lazy","dog"],group->maxByLength.[["the"],["quick"],["brown"],["fox"],

["jumps"],["over"],["the"],["lazy"],["dog"]],maxByLength->head.["dog"],_c5 >

Cases: 1 Tried: 1 Errors: 0 Failures: 1

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Test Failure – Trace

Again, this example is covered in detail in my original blog article:http://chplib.wordpress.com/2009/11/02/

concurrent-testing-and-tracing-useful-output-for-test-failures/

Page 86: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Process Wiring

Page 87: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

Page 88: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

?p q

Page 89: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

=p q r

r = p <=>q

Page 90: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

??

p q

Page 91: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

p q = r

r = p <=>q

Page 92: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Wiring processes in a line is easy

p q = r

r = p <=>q

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

Wiring processes in a line is easy

The point here is that it should be easy to join together two processeswith corresponding interfaces.

Page 93: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable Type-Class

class Connectable l r where ...

Page 94: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable Type-Class

class Connectable l r where ...

instance Connectable (Chanin a) (Chanout a) where ...

Page 95: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable Type-Class – Pairs

class Connectable l r where ...

instance Connectable (Chanin a) (Chanout a) where ...

instance (Connectable lA rA, Connectable lB rB) =>Connectable (lA, lB) (rA, rB) where ...

Page 96: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable operator

(<=>) :: Connectable l r =>(a -> l -> CHP ())

-> (r -> b -> CHP ())-> (a -> b -> CHP ())

Page 97: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable operator

(<=>) :: Connectable l r =>(a -> l -> CHP ())

-> (r -> b -> CHP ())-> (a -> b -> CHP ())

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Connectable operator

This corrects my earlier slide on the type of this operator; it is muchmore general than I had previously showed. Once again, more detailavailable on the blog:http://chplib.wordpress.com/2009/12/02/

automated-wiring-of-message-passing-processes/

Page 98: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable class allows us to abstract commontopologies; the cycle

cycleConnect :: Connectable l r =>[ r -> l -> CHP ()] -> CHP ()

diningPhilosophers= cycleConnect (concat (replicate 5 [ fork , philosopher]))

Page 99: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Connectable class allows us to abstract commontopologies; the wrapped grid (torus)

wrappedGrid :: (Connectable left right, Connectable above below) =>[[ left -> right -> above -> below -> CHP r]] -> CHP [[r]]

Page 100: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Quest for Higher Ground

f (x:xs) writeChannel

Page 101: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Quest for Higher Ground

f (x:xs) writeChannel

map, fold ***

Page 102: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

The Quest for Higher Ground

f (x:xs) writeChannel

map, fold ***

2010

-03-

16An Introduction ToCommunicating Haskell Processes(CHP)

The Quest for Higher Ground

Decomposing a list via pattern-matching is the lowest-level ofabstraction with lists, just like writeChannel is one of the most basicprimitives of CHP. But with lists we identify common patterns and usefunctions like map and fold; I believe that with concurrentprogramming we can similarly spot higher-level patterns to work with,and that’s what I’m interested in.

Page 103: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Other Features

Synchronisation Primitives:ClocksBarriersConjoined Events

Higher-Level Features:BehavioursWiring monad

Formalisms:CSP model generationMore trace types

Page 104: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Other Features

Synchronisation Primitives:ClocksBarriersConjoined Events

Higher-Level Features:BehavioursWiring monad

Formalisms:CSP model generationMore trace types20

10-0

3-16

An Introduction ToCommunicating Haskell Processes(CHP)

Other Features

Most of these items can be found on the blog(http://chplib.wordpress.com/ if you look at the tags downthe right-hand side.

Page 105: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Summary

CHP enables a different style of programmingProgramming model composes and scalesAiming for a higher level of abstractionSome aspects are a natural extension of functionalprogramming: stream processing, evaluation-on-demand,process compositionLends itself well to diagrams

Page 106: An Introduction To Communicating Haskell Processes (CHP) · 2010. 3. 16. · An Introduction ToCommunicating Haskell Processes(CHP) The Basic API (2/2) We distinguish between the

Questions?

Available on Hackage as “chp” and “chp-plus”Lighter-weight synchronous channels available as “sync”(mine) and “cml” (not mine)Examples and articles available on my blog:http://chplib.wordpress.com/