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?

+3


source to share


2 answers


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.

+5


source


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.

+2


source







All Articles