Confusion Over Applicative (->) - haskell

Given that Applicative (->) is implemented as:
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
I am confused how the following works:
pure (+) <*> Just 3
My understanding is that:
f = pure (+)
g = Just 3
Based on that understanding, <*> would become:
-- f x (g x)
(pure (+)) x ((Just 3) x)
But this does not work since (Just 3) takes no parameters. So I apparently must be unaware of something, though I am not sure what that is.
I am baffled as to how this happens:
Prelude> :t pure (+) <*> Just 3
pure (+) <*> Just 3 :: Num a => Maybe (a -> a)
Please explain how this works. Doing the steps manually, based on my understanding of things, I am not able to reach the same outcome as ghci.

Since the right-hand-side argument to <*> is Just 3, then the Applicative instance being used must be that of Maybe, not of functions. So, the left-hand side must be a Maybe as well, thus pure (+) == Just (+). Now you can see how <*> combines these: it unwraps the two Just constructors, applies the function, and puts the result back into a Just: this is the same as Just ((+) 3), or Just (3 +). And as you can see in ghci, those two things have the same type.

Related

Multiple arguments on applicatives not working?

So I'm trying to learn about monads, functors and applicatives. I've created the following renamed mirror match of Maybe called Sometimes. (I did this to learn about these things)
data Sometimes a = Nope | Thing a deriving Show
instance Monad Sometimes where
(Thing x) >>= f = f x
Nope >>= f = Nope
return = Thing
instance Applicative Sometimes where
pure = Thing
Nope <*> _ = Nope
(Thing g) <*> mx = fmap g mx
instance Functor Sometimes where
fmap _ Nope = Nope
fmap g (Thing x) = Thing (g x)
So when I do the following it works:
pure (1+) <*> (Thing 1)
> Thing 2
pure (+) <*> (Thing 1) <*> (Thing 1)
> Thing 2
But if I try three additions it doesn't work:
pure (+) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
<interactive>:108:1: error:
• Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => Sometimes b
Why doesn't this work? I would expect the first two to be applied and then the third to be applied to the result of the first two. My book talks about how implementing fmap0, fmap1, fmap2... is inefficient and as such
... for functions with any desired number of arguments can be constructed in terms of two basic functions with the following types:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
And states further on:
A typical use of pure and <*> has the following form:
pure g <*> x1 <*> x2 <*> ... <*> xn
As such I'm expecting it to work but I'm clearly missing something in my definitions/usage of the Applicative.
I'm using the book Programming in Haskell SE by Graham Hutton
The reason this does not work is because (+) sums two numbers, not three.
You can make a function that sums three numbers, for example with:
pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
this then gives us:
Prelude> pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
Thing 3
Why doesn't this work? I would expect the first two to be applied and then the third to be applied to the result of the first two.
Exactly, but after the first two are applied, this is no longer a function, but a Num a => Sometimes a. Indeed, if we determines the types, we see that Thing (+) :: Num a => Sometimes (a -> a -> a) and Thing 1 :: Num b => Sometimes b, so that means that Thing (+) <*> Thing 1 has type Num a => Sometimes (a -> a).
Then we determine the type of Thing (+) <*> Thing 1 <*> Thing 1, since Thing (+) <*> Thing 1 has type Num a => Sometimes (a -> a), and the last Thing 1 has type Num c => Sometimes c, it means that Thing (+) <*> Thing 1 <*> Thing 1 has type Num a => Sometimes a, but this is not a function, unless there is a Num type that is a function, which is what the error is saying.

Understanding Functions as Applicatives in Haskell

I've recently been trying to learn Haskell with the "Learn You a Haskell" and have been really struggling with understanding functions as Applicatives. I should point out that using other types of Applicatives like Lists and Maybe I seem to understand well enough to use them effectively.
As I tend to do when trying to understand something is I tried to play with as many examples as I could and once the pattern emerges things tend to make sense. As such I tried a few examples. Attached are my notes of several examples I tried along with a diagram I drew to try to visualize what was happening.
The definition of funct doesnt seem to relevant to the outcome but in my tests I used a function with the following definition:
funct :: (Num a) => a -> a -> a -> a
At the bottom I tried to show the same thing as in the diagrams just using normal math notation.
So all of this is well and good, I can understand the pattern when I have some function of an arbitrary number of arguments (though needs 2 or more) and apply it to a function that takes one argument. However intuitively this pattern doesn't make that much sense to me.
So here are the specific questions I have:
What is the intuitive way to understand the pattern I'm seeing, particularly if i view an Applicative as a container (which is how I view Maybe and lists)?
What is the pattern when the function on the right of the <*> takes more than a single argument (I've mostly been using the function (+3) or (+5) on the right)?
why is the function on the right hand side of the <*> applied to the second argument of the function on the left side. For example if the function on the right hand side were f() then funct(a,b,c) turns into funct (x, f(x), c)?
Why does it work for funct <*> (+3) but not for funct <*> (+)? Moreover it DOES work for (\ a b -> 3) <*> (+)
Any explanation that gives me a better intuitive understanding for this concept would be greatly appreciated. I read other explanations such as in the book I mentioned that explains functions in terms of ((->)r) or similar patterns but even though I know how to use the ->) operator when defining a function I'm not sure i understand it in this context.
Extra Details:
I want to also include the actual code I used to help me form the diagrams above.
First I defined funct as I showed above with:
funct :: (Num a) => a -> a -> a -> a
Throughout the process i refined funct in various ways to understand what was going on.
Next I tried this code:
funct a b c = 6
functMod = funct <*> (+3)
functMod 2 3
Unsuprisingly the result was 6
So now I tried just returning each argument directly like this:
funct a b c = a
functMod = funct <*> (+3)
functMod 2 3 -- returns 2
funct a b c = b
functMod = funct <*> (+3)
functMod 2 3 -- returns 5
funct a b c = c
functMod = funct <*> (+3)
functMod 2 3 -- returns 3
From this I was able to confirm the second diagram is what was taking place. I repeated this patterns to observe the third diagram as well (which is the same patterns extended on top a second time).
You can usually understand what a function is doing in Haskell if you
substitute its definition into some examples. You already have some
examples and the definition you need is <*> for (->) a which is
this:
(f <*> g) x = f x (g x)
I don't know if you'll find any better intuition than just using the
definition a few times.
On your first example we get this:
(funct <*> (+3)) x
= funct x ((+3) x)
= funct x (x+3)
(Since there was nothing I could do with funct <*> (+3) without a
further parameter I just applied it to x - do this any time you need
to.)
And the rest:
(funct <*> (+3) <*> (+5)) x
= (funct x (x+3) <*> (+5)) x
= funct x (x+3) x ((+5) x)
= funct x (x+3) x (x+5)
(funct <*> (+)) x
= funct x ((+) x)
= funct x (x+)
Notice you can't use the same funct with both of these - in
the first it can take four numbers, but in the second it needs to take
a number and a function.
((\a b -> 3) <*> (+)) x
= (\a b -> 3) x (x+)
= (\b -> 3) (x+)
= 3
(((\a b -> a + b) <*> (+)) x
= (\a b -> a + b) x (x+)
= x + (x+)
= type error
As pointed out by David Fletcher, (<*>) for functions is:
(g <*> f) x = g x (f x)
There are two intuitive pictures of (<*>) for functions which, though not quite able to stop it from being dizzying, might help with keeping your balance as you go through code that uses it. In the next few paragraphs, I will use (+) <*> negate as a running example, so you might want to try it out a few times in GHCi before continuing.
The first picture is (<*>) as applying the result of a function to the result of another function:
g <*> f = \x -> (g x) (f x)
For instance, (+) <*> negate passes an argument to both (+) and negate, giving out a function and a number respectively, and then applies one to the other...
(+) <*> negate = \x -> (x +) (negate x)
... which explains why its result is always 0.
The second picture is (<*>) as a variation on function composition in which the argument is also used to determine what the second function to be composed will be
g <*> f = \x -> (g x . f) x
From that point of view, (+) <*> negate negates the argument and then adds the argument to the result:
(+) <*> negate = \x -> ((x +) . negate) x
If you have a funct :: Num a => a -> a -> a -> a, funct <*> (+3) works because:
In terms of the first picture: (+ 3) x is a number, and so you can apply funct x to it, ending up with funct x ((+ 3) x), a function that takes two arguments.
In terms of the second picture: funct x is a function (of type Num a => a -> a -> a) that takes a number, and so you can compose it with (+ 3) :: Num a => a -> a.
On the other hand, with funct <*> (+), we have:
In terms of the first picture: (+) x is not a number, but a Num a => a -> a function, and so you can't apply funct x to it.
In terms of the second picture: the result type of (+), when seen as a function of one argument ((+) :: Num a => a -> (a -> a)), is Num a => a -> a (and not Num a => a), and so you can't compose it with funct x (which expects a Num a => a).
For an arbitrary example of something that does work with (+) as the second argument to (<*>), consider the function iterate:
iterate :: (a -> a) -> a -> [a]
Given a function and an initial value, iterate generates an infinite list by repeatedly applying the function. If we flip the arguments to iterate, we end up with:
flip iterate :: a -> (a -> a) -> [a]
Given the problem with funct <*> (+) was that funct x wouldn't take a Num a => a -> a function, this seems to have a suitable type. And sure enough:
GHCi> take 10 $ (flip iterate <*> (+)) 1
[1,2,3,4,5,6,7,8,9,10]
(On a tangential note, you can leave out the flip if you use (=<<) instead of (<*>). That, however, is a different story.)
As a final aside, neither of the two intuitive pictures lends itself particularly well to the common use case of applicative style expressions such as:
(+) <$> (^2) <*> (^3)
To use the intuitive pictures there, you'd have to account for how (<$>) for functions is (.), which murks things quite a bit. It is easier to just see the entire thing as lifted application instead: in this example, we are adding up the results of (^2) and (^3). The equivalent spelling as...
liftA2 (+) (^2) (^3)
... somewhat emphasises that. Personally, though, I feel one possible disadvantage of writing liftA2 in this setting is that, if you apply the resulting function right in the same expression, you end up with something like...
liftA2 (+) (^2) (^3) 5
... and seeing liftA2 followed by three arguments tends to make my brain tilt.
You can view the function monad as a container. Note that it's really a separate monad for every argument-type, so we can pick a simple example: Bool.
type M a = Bool -> a
This is equivalent to
data M' a = M' { resultForFalse :: a
, resultForTrue :: a }
and the instances could be defined
instance Functor M where instance Functor M' where
fmap f (M g) = M g' fmap f (M' gFalse gTrue) = M g'False g'True
where g' False = f $ g False where g'False = f $ gFalse
g' True = f $ g True g'True = f $ gTrue
and similar for Applicative and Monad.
Of course this exhaustive case-listing definition would become totally impractical for argument-types with more than a few possible values, but it's always the same principle.
But the important thing to take away is that the instances are always specific for one particular argument. So, Bool -> Int and Bool -> String belong to the same monad, but Int -> Int and Char -> Int do not. Int -> Double -> Int does belong to the same monad as Int -> Int, but only if you consider Double -> Int as an opaque result type which has nothing to do with the Int-> monad.
So, if you're considering something like a -> a -> a -> a then this is not really a question about applicatives/monads but about Haskell in general. And therefore, you shouldn't expect that the monad=container picture gets you anywhere. To understand a -> a -> a -> a as a member of a monad, you need to pick out which of the arrows you're talking about; in this case it's only the leftmost one, i.e. you have the value M (a->a->a) in the type M=(a->) monad. The arrows between a->a->a do not participate in the monadic action in any way; if they do in your code, then it means you're actually mixing multiple monads together. Before you do that, you should understand how a single monad works, so stick to examples with only a single function arrow.

what does (<*>) :: f (a -> b) -> f a -> f b exactly do in the Functor class

class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
From my understanding, it takes a function f, where another function (a -> b) as its argument, returns a function f. Applying f to a then returns a function f and apply f to b.
Here is an example:
Prelude> (+) <$> Just 2 <*> Just 3
Just 5
But I don't quite understand how it works.
I guess (+) should be f, Just 2 and Just 3 should be a and b respectively. Then what is (a -> b)?
From my understanding, it takes a function f...
Unfortunately this is incorrect. In this case, f is a type, not a function. Specifically, f is a "higher-kinded type" with kind * -> *. The type f is the functor.
In this case, f is Maybe. So we can rewrite the function types, specializing them for Maybe:
pure :: a -> Maybe a
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
It starts to become a bit clearer once you get this far. There are a couple different possible definitions for pure, but only one that makes sense:
pure = Just
The operator x <$> y is the same as pure x <*> y, so if you write out:
(+) <$> Just 2 <*> Just 3
Then we can rewrite it as:
pure (+) <*> pure 2 <*> pure 3
Although this technically has a more general type. Working with the functor laws, we know that pure x <*> pure y is the same as pure (x y), so we get
pure ((+) 2) <*> pure 3
pure ((+) 2 3)
pure (2 + 3)
In this case, we a and b are the types but since <*> appears twice they actually have different types in each case.
In the first <*>, a is Int and b is Int -> Int.
In the second <*>, both a and b are Int. (Technically you get generic versions of Int but that's not really important to the question.)
Applicative functors were introduced to Haskell as applicative style programming "Idioms". Unpacking this phrase, we have "applicative style programming"; which is just application of functions to arguments. We also have "idioms", or phrases in a language which have a special meaning. For example "raining cats and dogs" is an idiom for raining very heavily. Putting them together, applicative functors are function applications with special meaning.
Take for example, following Dietrich Epp's lead, anApplication defined by a function,
anApplication = f a
where
f = (+2)
a = 3
and, anIdiomaticApplication, defined with idiomatic application,
anIdiomaticApplication = f <*> a
where
f = Just (+2)
a = Just 3
The top level structure of these definitions are similar. The difference? The first has a space--normal function application--and the second has <*>--idiomatic function application. This illustrates how <*> facilitates applicative style: just use <*> in place of a space.
The application, <*>, is idiomatic because it carries a meaning other than just pure function application. By way of exposition, in anIdiomaticApplication we have something like this:
f <*> a :: Maybe (Int -> Int) <*> Maybe Int
Here, the <*> in the type is used to represent a type level function* that corresponds to the signature of the real <*>. To the type-<*> we apply the type arguments for f and a (respectively Maybe (Int -> Int) and Maybe Int). After application we have
f <*> a :: Maybe Int
As an intermediate step, we can imagine something like
f <*> a :: Maybe ((Int -> Int) _ Int)
With _ being the type level stand-in for regular function application.
At this point we can finally see the idiom-ness called out. f <*> a is like a normal function application, (Int -> Int) _ Int, in the Maybe context/idiom. So, <*> is just function application that happens within a certain context.
In parting, I'll emphasize that understanding <*> is only partially understanding its use. We can understand that f <*> a is just function application which some extra idiomatic meaning. Due to the Applicative laws, we can also assume that idiomatic application will be somehow sensible.
Don't be surprised, however, if you look at <*> and get confused since there is so little there. We must also be versed in the various Haskell Idioms. For instance, in the Maybe idiom either the function or value may not be present, in which case the output will be Nothing. There are of course, many others, but getting familiar with just Either a and State s should model a wide variety of the different kinds.
*Something like this could actually be made with a closed type family (untested)
type family IdmApp f a where
IdmApp (f (a->b)) a = f b

(r ->) applicative functor

I am having some trouble understanding how the function instance (->) r of Applicative works in Haskell.
For example if I have
(+) <$> (+3) <*> (*100) $ 5
I know you get the result 508, I sort of understand that you take the result of (5 + 3) and (5 * 100) and you apply the (+) function to both of these.
However I do not quite understand what is going on. I assume that the expression is parenthesized as follows:
((+) <$> (+3)) <*> (*100)
From my understanding what is happening is that your mapping (+) over the eventual result of (+3) and then you are using the <*> operator to apply that function to the eventual result of (*100)
However I do not understand the implementation of <*> for the (->) r instance and why I cannot write:
(+3) <*> (*100)
How does the <*>, <$> operator work when it comes to (->) r?
<$> is just another name for fmap and its definition for (->) r is (.) (the composition operator):
intance Functor ((->) r) where
fmap f g = f . g
You can basically work out the implementation for <*> just by looking at the types:
instance Applicative ((->) r) where
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
f <*> g = \x -> f x (g x)
You have a function from r to a to b and a function from r to a. You want a funtion from r to b as a result. First thing you know is you return a function:
\x ->
Now you want to apply f since it is the only item which may return a b:
\x -> f _ _
Now the arguments for f are of type r and a. r is simply x (since it alrady is of type r and you can get an a by applying g to x:
\x -> f x (g x)
Aaand you're done. Here's a link to the implementation in Haskell's Prelude.
Consider the type signature of <*>:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Compare this to the type signature for ordinary function application, $:
($) :: (a -> b) -> a -> b
Notice that they are extremely similar! Indeed, the <*> operator effectively generalizes application so that it can be overloaded based on the types involved. This is easy to see when using the simplest Applicative, Identity:
ghci> Identity (+) <*> Identity 1 <*> Identity 2
Identity 3
This can also be seen with slightly more complicated applicative functors, such as Maybe:
ghci> Just (+) <*> Just 1 <*> Just 2
Just 3
ghci> Just (+) <*> Nothing <*> Just 2
Nothing
For (->) r, the Applicative instance performs a sort of function composition, which produces a new function that accepts a sort of “context” and threads it to all of the values to produce the function and its arguments:
ghci> ((\_ -> (+)) <*> (+ 3) <*> (* 100)) 5
508
In the above example, I have only used <*>, so I’ve explicitly written out the first argument as ignoring its argument and always producing (+). However, Applicative typeclass also includes the pure function, which has the same purpose of “lifting” a pure value into an applicative functor:
ghci> (pure (+) <*> (+ 3) <*> (* 100)) 5
508
In practice, though, you will rarely see pure x <*> y because it is precisely equivalent to x <$> y by the Applicative laws, since <$> is just an infix synonym for fmap. Therefore, we have the common idiom:
ghci> ((+) <$> (+ 3) <*> (* 100)) 5
508
More generally, if you see any expression that looks like this:
f <$> a <*> b
…you can read it more or less like the ordinary function application f a b, except in the context of a particular Applicative instance’s idioms. In fact, an original formulation of Applicative proposed the idea of “idiom brackets”, which would add the following as syntactic sugar for the above expression:
(| f a b |)
However, Haskellers seem to be satisfied enough with the infix operators that the benefits of adding the additional syntax has not been deemed worth the cost, so <$> and <*> remain necessary.
Let's take a look at the types of these functions (and the definitions that we automatically get along with them):
(<$>) :: (a -> b) -> (r -> a) -> r -> b
f <$> g = \x -> f (g x)
(<*>) :: (r -> a -> b) -> (r -> a) -> r -> b
f <*> g = \x -> f x (g x)
In the first case, <$>, is really just function composition. A simpler definition would be (<$>) = (.).
The second case is a little more confusing. Our first input is a function f :: r -> a -> b, and we need to get an output of type b. We can provide x :: r as the first argument to f, but the only way we can get something of type a for the second argument is by applying g :: r -> a to x :: r.
As an interesting aside, <*> is really the S function from SKI combinatory calculus, whereas pure for (-> r) is the K :: a -> b -> a (constant) function.
As a Haskell newbie myself, i'll try to explain the best way i can
The <$> operator is the same as mapping a function on to another function.
When you do this:
(+) <$> (+3)
You are basically doing this:
fmap (+) (+3)
The above will call the Functor implementation of (->) r which is the following:
fmap f g = (\x -> f (g x))
So the result of fmap (+) (+3) is (\x -> (+) (x + 3))
Note that the result of this expression has a type of a -> (a -> a)
Which is an applicative! That is why you can pass the result of (+) <$> (+3) to the <*> operator!
Why is it an applicative you might ask? Lets look the at the <*> definition:
f (a -> b) -> f a -> f b
Notice that the first argument matches our returned function definition a -> (a -> a)
Now if we look at the <*> operator implementation, it looks like this:
f <*> g = (\x -> f x (g x))
So when we put all those pieces together, we get this:
(+) <$> (+3) <*> (+5)
(\x -> (+) (x + 3)) <*> (+5)
(\y -> (\x -> (+) (x + 3)) y (y + 5))
(\y -> (+) (y + 3) (y + 5))
The (->) e Functor and Applicative instances tend to be a bit confusing. It may help to view (->) e as an "undressed" version of Reader e.
newtype Reader e a = Reader
{ runReader :: e -> a }
The name e is supposed to suggest the word "environment". The type Reader e a should be read as "a computation that produces a value of type a given an environment of type e".
Given a computation of type Reader e a, you can modify its output:
instance Functor (Reader e) where
fmap f r = Reader $ \e -> f (runReader r e)
That is, first run the computation in the given environment, then apply the mapping function.
instance Applicative (Reader e) where
-- Produce a value without using the environment
pure a = Reader $ \ _e -> a
-- Produce a function and a value using the same environment;
-- apply the function to the value
rf <*> rx = Reader $ \e -> (runReader rf e) (runReader rx e)
You can use the usual Applicative reasoning for this as any other applicative functor.

Applicative's Interchange Law

Applicative Programming with Effects, the paper from McBride and Paterson, presents the interchange law:
u <*> pure x = pure (\f -> f x) <*> u
In order to try to understand it, I attempted the following example - to represent the left-hand side.
ghci> Just (+10) <*> pure 5
Just 15
How could I write this example using the right-hand side?
Also, if u is an f (a -> b) where f is an Applicative, then what's the function on the right-hand side: pure (\f -> f x) ...?
It would be written as
pure (\f -> f 5) <*> Just (+10)
Or even
pure ($ 5) <*> Just (+10)
Both are equivalent in this case. Quite literally, you're wrapping a function with pure that takes another function as its argument, then applies x to it. You provide f as the contents of the Just, which in this case is (+10). When you see the lambda syntax of (\f -> f x), it's being very literal, this is a lambda used for this definition.
The point this law makes is about preservation of exponential by the Applicative Functor: what is a exponential in the origin, is also an exponential in the image of the category.
Please, observe that the actual action of the Applicative Functor is the transformation of the following kind: strength :: (f a, f b) -> f (a, b); then ap or <*> is just fmap eval over the result, or, written fully, ap = curry $ fmap (uncurry ($)) . strength.
This law then says that since in the origin g $ x == ($ x) $ g, lifting ($), x and ($ x) should preserve the equality. Notice, that "normal" Functors will only preserve the equality only if g is lifted, too, but Applicative Functors will preserve this equality for any object of type f (a->b) in place of g. This way the whole type f (a->b) behaves like f a -> f b, whereas for "normal" Functors it only needs to behave like f a -> f b for images of the arrows in the origin (to make the diagrams commute and fulfill the promises of the Functor).
As to representing the right-hand-side of the law, you've already been advised to take it literally, pure ($ 5) <*> Just (+10)

Resources