I am getting into Haskell and found the book "learn you a Haskell" most helpful. I am up to the section on applicative functors.
I am puzzled by the following as it appears in the book:
(\x y z -> [x, y, z]) <$> (+3) <*> (*2) <*> (/2) $ 5
which yields the output:
[8.0,10.0,2.5]
First of all, I have confirmed my suspicion in ghci in regards to precedence of the operators, so that the above equals the following ugly statement:
(((\x y z -> [x,y,z]) <$> (+3)) <*> (*2) <*> (/2)) $ 5
So from that it becomes clear that the first thing that happens is the fmap
call via the (<$>)
infix operator.
And this is the core of what boggles my mind currently.
The definition of fmap
(here shown as infix (<$>)
) is:
(<$>) :: (Functor f) => (a -> b) -> f a -> f b
But in the equation I am struggling with, (\x y z -> [x, y, z])
takes three arguments, not just one. So how could the first argument of type (a -> b)
be satisfied?
I think it might have to do with partial application / currying but I cannot figure it out. I would greatly appreciate an explanation. Hope I have formulated the question well enough.
Every Monad is an Applicative Just as IO , every monad can be made into an applicative functor.
The expression fmap (*2) is a function that takes a functor f over numbers and returns a functor over numbers. That functor can be a list, a Maybe , an Either String, whatever. The expression fmap (replicate 3) will take a functor over any type and return a functor over a list of elements of that type.
fmap is used to apply a function of type (a -> b) to a value of type f a , where f is a functor, to produce a value of type f b . Note that for any type constructor with more than one parameter (e.g., Either ), only the last type parameter can be modified with fmap (e.g., b in `Either a b`).
Applicative functors are the programming equivalent of lax monoidal functors with tensorial strength in category theory. Applicative functors were introduced in 2008 by Conor McBride and Ross Paterson in their paper Applicative programming with effects.
Simple answer: there are no functions with multiple arguments in Haskell!
There are two candidates for what you might call "dyadic function": a function that takes a (single!) tuple, and – by far prevalent in Haskell – curried functions. Those take just one argument, but the result is a function again.
So, to figure out what e.g. fmap (+)
does, let's write
type IntF = Int -> Int
-- (+) :: Int -> IntF
-- fmap :: ( a -> b ) -> f a -> f b
-- e.g.:: (Int->IntF) -> f Int->f IntF
Test it yourself in GHCi:
Prelude> type IntF = Int -> Int
Prelude> let (#) = (+) :: Int -> IntF
Prelude> :t fmap (#)
fmap (#) :: Functor f => f Int -> f IntF
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