# Compose

### From HaskellWiki

Revision as of 19:16, 14 May 2006 by DavidHouse (Talk | contribs)

Compose

compose :: [(a -> a)] -> (a -> a)

compose [(*2), (+1)] 3 = 8

This page illustrates the solution in different monads. Most are a bit of a joke; you'd probably only ever use the first solution presented, but nevertheless the nice features of the various monads are demonstrated.

## Contents |

## 1 The Sane Solution

compose :: [(a -> a)] -> a -> a compose fs v = foldl (flip (.)) id fs $ v

f . g

g

f

id

id

## 2 Using State

State

composeState :: [(a -> a)] -> a -> a composeState = execState . mapM modify

State

composeState fs v = execState (mapM modify fs) v

mapM

modify

fs = mapM modify [(*2), (+1), \n -> (n - 5) * 4] -- fs is entirely equivalent to the following do-block: fs' = do modify (*2) modify (+1) modify (\n -> (n - 5) * 4)

In other words, we obtain a stateful computation that modifies the state with the first function in the list, then the second, and so on.

## 3 Using Reader

Reader

composeReader :: [(a -> a)] -> a -> a composeReader fs v = runReader (compose' fs) v where compose' [] = ask compose' (f:fs) = local f (compose' fs)

Reader

State

modify

local

compose' fs

fs = compose' [(*2), (+1), \n -> (n - 5) * 4] -- again, this is entirely equivalent to the following: fs' = local (*2) $ local (+1) $ local (\n -> (n - 5) * 4) ask

ask

compose'

Once this composition has been built up, we run it, starting off with an environment of the starting value.

## 4 Using Writer

Writer

composeWriter :: [(a -> a)] -> a -> a composeWriter fs v = (snd $ runWriter $ compose' fs) v where compose' [] = return id compose' (f:fs) = censor (. f) (compose' fs)

Writer

Writer

Reader

Writer

censor

Writer

Writer

Once this computation has been build up, we extract this long composition chain, and apply it to our starting value.

## 5 The whole code

In case you wish to run this code, here it is in its entirety:

-- Thread a value through a list of function applications module Compose where import Control.Monad.Writer import Control.Monad.Reader import Control.Monad.State compose :: [(a -> a)] -> a -> a compose fs v = foldl (flip (.)) id fs $ v composeState :: [(a -> a)] -> a -> a composeState = execState . mapM modify composeReader :: [(a -> a)] -> a -> a composeReader fs v = runReader (compose' fs) v where compose' [] = ask compose' (f:fs) = local f (compose' fs) composeWriter :: [(a -> a)] -> a -> a composeWriter fs v = (snd $ runWriter $ compose' fs) v where compose' [] = return id compose' (f:fs) = censor (. f) (compose' fs) main = do let fs = [(+1), (*2), \n -> (n - 5) * 4] v = 3 putStrLn $ "compose: " ++ (show $ compose fs v) putStrLn $ "compostState: " ++ (show $ composeState fs v) putStrLn $ "composeReader: " ++ (show $ composeReader fs v) putStrLn $ "composeWriter: " ++ (show $ composeWriter fs v) {- *Compose> main compose: 12 compostState: 12 composeReader: 12 composeWriter: 12 -}