g()
return?
f(3)
return?
f
has the same type as in the previous example.
g()
return?
f
has the same type as in the previous examples.
newPage
changes the state
(has both extra input and extra output).
startNewPage
changes the state and performs IO operations.
f
has the same type as in the previous examples.
All inputs and outputs have to be visible in the type:
Pure function: | ÂInput -> Output |
Extra input: | ÂInput -> Extra -> Output |
Extra output: | ÂInput -> (Extra,Output)Â |
Changing the state: | ÂInput -> State -> (State,Output)Â |
IO operations: | ÂInput -> IO Output |
Sometimes no result: | ÂInput -> Maybe Output |
Many results: | ÂInput -> [Output]Â |
h
that combines two functions
f
and g
that both have additional effects.
-- Pure functions: Input -> Output h x = g (f x) -- Extra input: Input -> Extra -> Output h x e = g (f x e) e
-- Extra output: Input -> (Extra,Output) h x = (o1<>o2,y2) where (o1,y1) = f x (o2,y2) = g y1 -- Changing the state: Input -> State -> (State,Output) h x s0 = (s2,y2) where (s1,y1) = f x s0 (s2,y2) = g y1 s1
-- IO operations: Input -> IO Output h x = do y1 <- f x y2 <- g y1 return y2 -- Sometimes no result: Input -> Maybe Output h x = case f x of Nothing -> Nothing Just y -> g y -- Many results: h x = [y2 | y1 <- f x, y2 <- g y1]
h x = (o1<>o2,y2) where (o1,y1) = f x (o2,y2) = g y1
h x = g =<< f x
h x = (o1<>o2,y2) where (o1,y1) = f x (o2,y2) = g y1
h x = g =<< f x
g =<< fx = (o1<>o2,y2) where (o1,y1) = fx (o2,y2) = g y1
Taking another look at the types:
Type of effect | Function type |
---|---|
Pure function: | ÂInput -> Output |
Extra input: | ÂInput -> Extra -> Output |
Extra output: | ÂInput -> (Extra,Output)Â |
Changing the state: | ÂInput -> State -> (State,Output)Â |
IO operations: | ÂInput -> IO Output |
Sometimes no result: | ÂInput -> Maybe Output |
Many results: | ÂInput -> [Output]Â |
We can factor them like this:
Type of effect | The common pattern | The difference |
---|---|---|
Pure function: | ÂInput -> M Output | ÂM a a |
Extra input: | ÂInput -> M Output | ÂM a Extra -> a |
Extra output: | ÂInput -> M Output | ÂM a (Extra,a) |
Changing the state: | ÂInput -> M Output | ÂM a State->(State,a) |
IO operations: | ÂInput -> M Output | ÂM a IO a |
Sometimes no result: | ÂInput -> M Output | ÂM a Maybe a |
Many results: | ÂInput -> M Output | ÂM a [a] |
Input -> M OutputÂ
MÂ
MÂ
(=<<) :: (a -> M b) -> M a -> M b
($) :: (a -> b) -> a -> b
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a->m b) -> m b
-- ...
(=<<) :: Monad m => (a->m b) -> m a -> m b
f=<<x = x>>=f
mÂ
Operator  | Function | Argument | Result |
---|---|---|---|
‹$› |    a->b | Âa |   b |
‹<$>› |    a->b | Âm a | Âm b |
‹<*>› | Âm (a->b)   | Âm a | Âm b |
‹=<<› |  a->m b  | Âm a | Âm b |
f <$> x = fmap f x f =<< m = m >>= f
class Functor f where fmap :: (a->b) -> f a -> f b f <$> x = fmap f x
map :: (a->b) -> [a] -> [b] fmap :: Functor f => (a->b) -> f a -> f b
rNumeric :: Gen Rank rNumeric = do n <- choose (2,10) return (Numeric n)
rNumeric = Numeric <$> choose (2,10)
number :: Parser Integer number = do ds <- oneOrMore digit return (read ds)
number = read <$> oneOrMore digit
class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a->b) -> f a -> f b
ApplicativeÂ
MonadÂ
rCard :: Gen Card rCard = do s <- rSuit r <- rRank return (Card s r)
rCard = Card <$> rSuit <*> rRank
oneOrMore :: Parser item -> Parser [item] oneOrMore item = do i <- item is <- zeroOrMore item return (i:is)
oneOrMore item = (:) <$> item <*> zeroOrMore item
EitherÂ
MaybeÂ