The easy way to use multiple arguments in Haskell
A value f
with a type :: Applicative f => f (a -> b -> c)
. How can the arguments of the inner function be matched.
So far I have found the following:
(\x -> x a b) <$> f
(flip ($ a) b) <$> f
($ b) <$> ($ a) <$> f
I think my question is why Haskell doesn't have a function :: a -> b -> (a -> b -> c) -> c
. Or that?
source to share
The class Applicative
has an operator <*>
(usually pronounced "ap" and is equivalent Control.Monad.ap
for most Monad
s), which when combined with an operator <$>
(itself is just an alias for infix fmap
), allows you to write code like
-- f :: a -> b -> c
-- fa :: Applicative f => f a
-- fb :: Applicative f => f b
f <$> fa <*> fb :: Applicative f => f c
If you need to apply pure arguments, use a pure
class method Applicative
:
-- f :: a -> b -> c
-- a :: a
-- b :: b
f <$> pure a <*> pure b :: Applicative f => f c
An example would be
sumOfSquares :: Num a => a -> a -> a
sumOfSquares a b = a * a + b * b
> sumOfSquares <$> Just 1 <*> Just 2
Just 5
> sumOfSquares <$> Just 1 <*> Nothing
Nothing
> sumOfSquares <$> pure 1 <*> pure 2 :: Maybe Int
5
> sumOfSquares <$> readLn <*> readLn :: IO Int
1<ENTER>
2<ENTER>
5
It Applicative f => f (a -> b -> c)
builds here f <$>
, so if you already have something like
> let g :: IO (Int -> Int -> Int); g = undefined
Then you can just use it like
> g <*> pure 1 <*> pure 2
The operator <*>
is of type
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
so if your function is of type x -> y -> z
, then a ~ x
and b ~ y -> z
, so repeated ap posting <*>
(get it?) passes more arguments to your wrapped function.
source to share
We have
(<$>) :: Functor f => (a -> b) -> f a -> f b
But you want the opposite
(>$<) :: Functor f => f (a -> b) -> a -> f b
What we can easily define:
(>$<) f a = ($a) <$> f
So given
f :: Functor f => f (a -> b -> c)
a :: a
b :: b
Then
f >$< a :: f (b -> c)
f >$< a >$< b :: f c
It's not as idiomatic as it is <*>
, but it works for all Functor
s, not just Applicative
s, which is nice.
source to share