Applicative Programming with Effects, the paper from McBride and Paterson, mentions the sequence
function:
sequence :: [IO a ] -> IO [a ]
sequence [] = return []
sequence (c : cs) = return (:) `ap` c `ap` sequence cs
where ap
's type is:
ap :: Monad m => m (a -> b) -> m a -> m b
I'm trying to understand the types of the last line's right-side.
How do the types unify (I think that's the correct wording) for return (:) 'ap' c 'ap' sequence cs
?
It's not clear to me how return (:)
matches ap
's first argument m (a -> b)
.
ghci> :t return (:)
return (:) :: Monad m => m (a -> [a] -> [a])
The answer is... currying!
The first argument to ap
has type m (a -> b)
, so the function expects
a value of type a
and will product a value of type b
. One possible thing
that b
could be is another function (i.e. b
could be unified with [a] -> [a]
). So, we line things up and get
ap :: Monad m => m (a -> b ) -> m a -> m b
==========
return (:) :: Monad m => m (a -> [a] -> [a])
The ap
function performs application of a function in some context (in this case a monad) to a value in that context, it just so happens that it is often used to perform a sequence of partial applications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With