Precedence Confusion about <$> and <*> in Haskell - haskell

Two examples both from http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors,
1). (+) <$> (+3) <*> (*100) $ 5
(+) <$> (+3) <*> (*100) $ 5, the 5 first got applied to (+3) and
(*100), resulting in 8 and 500. Then, + gets called with 8 and 500,
resulting in 508.
From the first example, it seems like <*> has higher precedence than <$>.
2). (++) <$> Just "johntra" <*> Just "volta"
(++) <$> Just "johntra" <*> Just "volta", resulting in a value
that's the same as Just ("johntra"++),and now Just ("johntra"++) <*>
Just "volta" happens, resulting in Just "johntravolta".
From the second example, it seems like <$> has higher precedence than <*>.
So do they have the same precedence? can someone give me some explanations/references?

indeed they both have the same precedence (infixl 4: (<*>) and (<$>)) and you can just read it from left to right -
(+) <$> (+3) <*> (*100) $ 5
= ((+) <$> (+3)) <*> (*100) $ 5
= (\ a b -> (a+3) + b) <*> (\ a -> a*100) $ 5
= (\ a -> (a+3) + (a*100)) $ 5
= 8 + 500 = 508
remember in this case we have f <*> g = \x -> f x (g x)

<$> and <*> has same precedence and left associativity. $ has the lowest precedence of zero. You can use ghci to explore information about them:
λ> :i (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
-- Defined in ‘Data.Functor’
infixl 4 <$>
λ> :i (<*>)
class Functor f => Applicative (f :: * -> *) where
...
(<*>) :: f (a -> b) -> f a -> f b
...
-- Defined in ‘Control.Applicative’
infixl 4 <*>
Now you can work out the types to see how they typecheck.

Related

How to combine two composed applicative functors?

I have two composed applicative functors Maybe [Integer] and want to combine them with <$>/<*> but I am stuck with applying the applicative operation. The following does not typecheck:
(<*>) (<*>) ((<$>) ((+) <$>) $ Just [1,2,3]) $ Just [4,5,6]
Expected result:
Just [5,6,7,6,7,8,7,8,9]
The functor part works, i.e. the intermediate value passed to <*> as the first argument is Just [Integer -> Integer]. I am used to S-expressions so I have a hard time with the Haskell syntax. I know of Compose but I am interested in the mere composition wihtout abstraction.
As Li-yao Xia said, using liftA2 makes it a lot less confusing.
But if you still what to see what it becomes in terms of the underlaying operations, we can expand the definition of liftA2:
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x y = f <$> x <*> y
so the solution becomes
(liftA2 . liftA2) (+) (Just [1,2,3]) (Just [4,5,6])
= liftA2 (liftA2 (+)) (Just [1,2,3]) (Just [4,5,6])
= (\f x y -> f <$> x <*> y) ((\f x y -> f <$> x <*> y) (+)) (Just [1,2,3]) (Just [4,5,6])
= ((\f x y -> f <$> x <*> y) (+)) <$> Just [1,2,3] <*> Just [4,5,6]
= (\x y -> (+) <$> x <*> y) <$> Just [1,2,3] <*> Just [4,5,6]
Now, this is not in point free style like your example above, and I really don't think it's helpful to convert it into point free, but here's the output from http://pointfree.io:
((<*>) . ((+) <$>)) <$> Just [1, 2, 3] <*> Just [4, 5, 6]
we can see that this is the same by eta-expanding:
(<*>) . ((+) <$>)
= \x y -> ((<*>) . ((+) <$>)) x y
= \x y -> ((<*>) $ ((+) <$>) x) y
= \x y -> ((<*>) ((+) <$> x)) y
= \x y -> (<*>) ((+) <$> x) y
= \x y -> ((+) <$> x) <*> y
= \x y -> (+) <$> x <*> y
liftA2 might be less confusing for this than (<*>).
(+) :: Int -> Int -> Int
liftA2 (+) :: [Int] -> [Int] -> [Int]
liftA2 (liftA2 (+)) :: Maybe [Int] -> Maybe [Int] -> Maybe [Int]
liftA2 (liftA2 (+)) (Just [1,2,3]) (Just [4,5,6])
The composition of two Applicatives is always an Applicative (unlike the case for Monad).
We can use this to our advantage here with the Compose newtype from Data.Functor.Compose:
newtype Compose f g a = Compose { getCompose :: f (g a) }
It requires a bit of wrapping, but this kind of solution could be useful under the right circumstances:
example :: Maybe [Int]
example =
getCompose ((+) <$> Compose (Just [1,2,3]) <*> Compose (Just [4,5,6]))
One other way could be to use the ListT transformer. While it works just fine in this case, for some reason it's a depreciated transformer, marked in red with "Deprecated: This transformer is invalid on most monads".
import Control.Monad.Trans.List
doit :: (Int-> Int -> Int) -> Maybe [Int] -> Maybe [Int] -> Maybe [Int]
doit f mt1 mt2 = runListT $ f <$> (ListT mt1) <*> (ListT mt2)
λ> doit (+) (Just [1,2,3]) (Just [4,5,6])
Just [5,6,7,6,7,8,7,8,9]

The composition law of Applicative in the Typeclassopedia

I am reading Typeclassopedia and I was having trouble in the section on Applicatives. I think I (sort of) have it figured out but I want to see if my understanding is correct.
The laws for applicative made sense right up until the Composition law. I just couldn't parse the right-hand side of this:
u <*> (v <*> w) = pure (.) <*> u <*> v <*> w
So, I fired up GHCI and ran some experiments.
Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just 34
Just 37
So this verifies the law, but I still didn't understand it. I tried some variations to see if I could get some insight:
Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just (+3) <*> Just 34
<interactive>:26:1: error:
* Non type-variable argument in the constraint: Num (b -> b)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall b. (Num (b -> b), Num b) => Maybe b
So, composition works for two functions but not for three? I didn't understand why.
I then verified that <*> worked as I thought it would for a simple expression:
Prelude> Just (+1) <*> Just 1
Just 2
However, the following didn't work:
Prelude> Just (+1) <*> Just (+2) <*> Just 34
<interactive>:15:2: error:
* Non type-variable argument in the constraint: Num (b -> b)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall b. (Num (b -> b), Num b) => Maybe b
So, application isn't the same as composition. I had thought that Just (+2) <*> Just 34 would have resulted in Just 36 and Just (+1) <*> Just 36 would have resulted in Just 37. The composition operator, (.), is needed, but it only works for two functions. I just didn't understand why it was needed or how it worked.
And, just to throw more dirt into this water, I tried the following:
Prelude> Just (,) <*> Just 2
which failed because there was no instance of Show for the result. So I tried:
Prelude> :t Just (,) <*> Just 2
Just (,) <*> Just 2 :: Num a => Maybe (b -> (a, b))
This gave me a bit of insight. I needed to pass a second value to get a tuple returned. I tried:
Prelude> Just (,) <*> Just 2 Just 34
but that failed, and the error message really didn't help me figure out just where the error was. So, looking at the type of the above code I realized that it was the same as if I had entered Just (2, ) (or something like it, anyway). So, I tried:
Prelude> Just (,) <*> Just (2) <*> Just 34
Just (2,34)
I was actually surprised that this worked. But in that surprise came the germ of understanding (I think).
I went back to the definition of (<*>) in Typeclassopedia and discovered it is defined as left associative. I hadn't even considered associativity before this. So the above expression would actually evaluate something like this:
Prelude> Just (,) <*> Just (2) <*> Just 34
-- Apply the 2 as the first parameter of (,) leaving a function
-- that takes the second parameter
Just (2,) <*> Just 34
-- Now apply the 34 as the parameter to the resulting function
Just (2,34)
If this is correct then the example of the Composition law that worked evaluates like this:
Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just 34
pure (+1 . ) <*> Just (+2) <*> Just 34
pure (+1 . +2) <*> Just 34
Just 37
This also explains why three functions cannot be composed this way:
Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just (+3) <*> Just 34
pure (+1 . ) <*> Just (+2) <*> Just (+3) <*> Just 34
pure (+1 . +2) <*> Just (+3) <*> Just 34
And, at this point we have a composed function expecting an instance of the Num typeclass but are, instead, passing it a function, which fails.
In a similar manner:
Prelude> Just (+1) <*> Just (+2) <*> Just 34
fails because <*> isn't composition and is trying to apply a function, (+2) to another function, (+1), and running into a type constraint.
So, is my intuition correct here? Have I finally figured this out? Or is my (somewhat) educated guess still off base?
This is just a case of not applying the substitution rule correctly, and forgetting the importance of parentheses in these substitutions (although some of them can be dropped later). The rule should be expressed as
u <*> (v <*> w) == (pure (.) <*> u <*> v) <*> w
Then
Just (+1) <*> (Just (+2) <*> Just 34)
-- u = Just (+1)
-- v = Just (+2)
-- w = Just 34
=> (pure (.) <*> u <*> v) <*> w
=> (pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34
To add another layer on this, you have to use another pure (.):
Just (+3) <*> (Just (+1) <*> (Just (+2) <*> Just 34))
-- u = Just (+3)
-- v = Just (+1)
-- w = Just (+2) <*> Just 34
=> (pure (.) <*> u <*> v) <*> w
=> pure (.) <*> Just (+3) <*> Just (+1) <*> (Just (+2) <*> Just 34)
If you wanted to work off of the pure form from the first stage, you'd have
Just (+3) <*> ((pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34)
-- u = Just (+3)
-- v = pure (.) <*> Just (+1) <*> Just (+2)
-- w = Just 34
=> (pure (.) <*> u <*> v) <*> w
=> pure (.) <*> Just (+3) <*> (pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34
Which isn't nearly as pretty as one would hope, I'm afraid.
As chi points out, your intuition is now correct. Quoting their comment:
Since (.) only composes two functions, it can't work on three.
This form of the composition law (i.e. in terms of (<*>)) is rather headache-inducing, specially if you want to work out further results using it (for a small example, cf. the latter part of bheklilr's answer). It gets a little easier to scan if we apply (pure f <*> x = f <$> x) to it:
u <*> (v <*> w) = ((.) <$> u <*> v) <*> w
Now the associativity in question is a little more obvious: applying v and then u to w through the functor is the same as composing u and v through the functor and then applying to w. For a major improvement, though, we have to switch to the so-called static arrow presentation:
idA :: Applicative f => f (a -> a)
idA = pure id
(.*) :: Applicative f => f (b -> c) -> f (a -> b) -> f (a -> c)
u .* v = (.) <$> u <*> v -- This looks familiar...
-- Conversely:
-- pure x = ($ x) <$> idA -- Alternatively: const x <$> idA
-- u <*> v = ($ ()) <$> (u .* (const <$> v))
In terms of (.*), the composition law becomes...
u .* (v .* w) = (u .* v) .* w
... which is transparently an associativity law.

Applicative: Prove `pure f <*> x = pure (flip ($)) <*> x <*> pure f`

During my study of Typoclassopedia I encountered this proof, but I'm not sure if my proof is correct. The question is:
One might imagine a variant of the interchange law that says something about applying a pure function to an effectful argument. Using the above laws, prove that:
pure f <*> x = pure (flip ($)) <*> x <*> pure f
Where "above laws" points to Applicative Laws, briefly:
pure id <*> v = v -- identity law
pure f <*> pure x = pure (f x) -- homomorphism
u <*> pure y = pure ($ y) <*> u -- interchange
u <*> (v <*> w) = pure (.) <*> u <*> v <*> w -- composition
My proof is as follows:
pure f <*> x = pure (($) f) <*> x -- identical
pure f <*> x = pure ($) <*> pure f <*> x -- homomorphism
pure f <*> x = pure (flip ($)) <*> x <*> pure f -- flip arguments
The first two steps of your proof look fine, but the last step doesn't. While the definition of flip allows you to use a law like:
f a b = flip f b a
that doesn't mean:
pure f <*> a <*> b = pure (flip f) <*> b <*> a
In fact, this is false in general. Compare the output of these two lines:
pure (+) <*> [1,2,3] <*> [4,5]
pure (flip (+)) <*> [4,5] <*> [1,2,3]
If you want a hint, you are going to need to use the original interchange law at some point to prove this variant.
In fact, I found I had to use the homomorphism, interchange, and composition laws to prove this, and part of the proof was pretty tricky, especially getting the sections right --like ($ f), which is different from (($) f). It was helpful to have GHCi open to double-check that each step of my proof type checked and gave the right result. (Your proof above type checks fine; it's just that the last step wasn't justified.)
> let f = sqrt
> let x = [1,4,9]
> pure f <*> x
[1.0,2.0,3.0]
> pure (flip ($)) <*> x <*> pure f
[1.0,2.0,3.0]
>
I ended up proving it backwards:
pure (flip ($)) <*> x <*> pure f
= (pure (flip ($)) <*> x) <*> pure f -- <*> is left-associative
= pure ($ f) <*> (pure (flip ($)) <*> x) -- interchange
= pure (.) <*> pure ($ f) <*> pure (flip ($)) <*> x -- composition
= pure (($ f) . (flip ($))) <*> x -- homomorphism
= pure (flip ($) f . flip ($)) <*> x -- identical
= pure f <*> x
Explanation of the last transformation:
flip ($) has type a -> (a -> c) -> c, intuitively, it first takes an argument of type a, then a function that accepts that argument, and in the end it calls the function with the first argument. So flip ($) 5 takes as argument a function which gets called with 5 as it's argument. If we pass (+ 2) to flip ($) 5, we get flip ($) 5 (+2) which is equivalent to the expression (+2) $ 5, evaluating to 7.
flip ($) f is equivalent to \x -> x $ f, that means, it takes as input a function and calls it with the function f as argument.
The composition of these functions works like this: First flip ($) takes x as it's first argument, and returns a function flip ($) x, this function is awaiting a function as it's last argument, which will be called with x as it's argument. Now this function flip ($) x is passed to flip ($) f, or to write it's equivalent (\x -> x $ f) (flip ($) x), this results in the expression (flip ($) x) f, which is equivalent to f $ x.
You can check the type of flip ($) f . flip ($) is something like this (depending on your function f):
λ: let f = sqrt
λ: :t (flip ($) f) . (flip ($))
(flip ($) f) . (flip ($)) :: Floating c => c -> c
I'd remark that such theorems are, as a rule, a lot less involved when written in mathematical style of a monoidal functor, rather than the applicative version, i.e. with the equivalent class
class Functor f => Monoidal f where
pure :: a -> f a
(⑂) :: f a -> f b -> f (a,b)
Then the laws are
id <$> v = v
f <$> (g <$> v) = f . g <$> v
f <$> pure x = pure (f x)
x ⑂ pure y = fmap (,y) x
a⑂(b⑂c) = assoc <$> (a⑂b)⑂c
where assoc ((x,y),z) = (x,(y,z)).
The theorem then reads
pure u ⑂ x = swap <$> x ⑂ pure u
Proof:
swap <$> x ⑂ pure u
= swap <$> fmap (,u) x
= swap . (,u) <$> x
= (u,) <$> x
= pure u ⑂ x
□

Using a pure function in a Haskell monad / left-lifting?

Consider the following function:
foo =
[1,2,3] >>=
return . (*2) . (+1)
For better readability and logic, I would like to move my pure functions (*2) and (+1) to the left of the return. I could achieve this like this:
infixr 9 <.
(<.) :: (a -> b) -> (b -> c) -> (a -> c)
(<.) f g = g . f
bar =
[1,2,3] >>=
(+1) <.
(*2) <.
return
However, I don't like the right-associativity of (<.).
Let's introduce a function leftLift:
leftLift :: Monad m => (a -> b) -> a -> m b
leftLift f = return . f
baz =
[1,2,3] >>=
leftLift (+1) >>=
leftLift (*2) >>=
return
I quite like this. Another possibility would be to define a variant of bind:
infixl 1 >>$
(>>$) :: Monad m => m a -> (a -> b) -> m b
(>>$) m f = m >>= return . f
qux =
[1,2,3] >>$
(+1) >>$
(*2) >>=
return
I am not sure whether that is a good idea, since it would not allow me to use do notation should I want that. leftLift I can use with do:
bazDo = do
x <- [1,2,3]
y <- leftLift (+1) x
z <- leftLift (*2) y
return z
I didn't find a function on Hoogle with the signature of leftLift. Does such a function exist, and, if, what is it called? If not, what should I call it? And what would be the most idiomatic way of doing what I am trying to do?
Edit: Here's a version inspired by #dunlop's answer below:
infixl 4 <&>
(<&>) :: Functor f => f a -> (a -> b) -> f b
(<&>) = flip fmap
blah =
[1,2,3] <&>
(+1) <&>
(*2) >>=
return
I should also add that I was after a bind-variant, because I wanted to write my code in point-free style. For do-notation, I guess I don't need to "pretend" that I'm doing anything monadic, so I can use lets.
Every Monad is a Functor (and an Applicative too). Your (>>$) is (flipped) fmap.
GHCi> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
GHCi> :t (<$>) -- Infix synonym for 'fmap'
(<$>) -- Infix synonym for 'fmap'
:: Functor f => (a -> b) -> f a -> f b
GHCi> fmap ((*2) . (+1)) [1,2,3]
[4,6,8]
GHCi> (*2) . (+1) <$> ([1,2,3] >>= \x -> [1..x])
[4,4,6,4,6,8]
(By the way, a common name for flipped fmap is (<&>). That is, for instance, what lens calls it.)
If you are using do-notation, there is little reason to use any variant of fmap explicitly for this kind of transformation. Just switch your <- monadic bindings for let-bindings:
bazDo = do
x <- [1,2,3]
let y = (+1) x
z = (*2) y
return z
bazDo = do
x <- [1,2,3]
let y = (+1) x
return ((*2) z)
For better readability...
That's going to be subjective as people disagree on what constitutes readable.
That being said, I agree that sometimes it's easier to understand data transformations when they are written left to right. I think your >>$ is overkill, though. The & operator in Data.Function does the job:
import Data.Function
foo = [1,2,3] & fmap (+1) & fmap (*2)
I like that this says exactly what to start with and exactly what to do at each step from left to right. And unlike >>$, you aren't forced to remain in the monad:
bar = [1,2,3] & fmap (+1) & fmap (*2) & sum & negate
Or you can just assemble your transformation beforehand and map it over your monad:
import Control.Category
f = (+1) >>> (*2)
quuz = fmap f [1,2,3]

How `sequenceA` works

I'm new to Haskell and trying to understand how does this work?
sequenceA [(+3),(+2),(+1)] 3
I have started from the definition
sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA [] = pure []
sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
And then unfolded recursion into this
(:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> pure []
(:) <$> (+3) <*> $ (:) <$> (+2) <*> $ (:) <$> (+1) <*> []
But here i don't understand for which applicative functor operator <*> will be called, for ((->) r) or for []
(:) <$> (+1) <*> []
Can somebody go step by step and parse sequenceA [(+3),(+2),(+1)] 3 step by step? Thanks.
This can be seen from the type of sequenceA:
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
The argument's outer type has to be a Traverable, and its inner type has to be Applicative.
Now, when you give sequenceA a list of functions (Num a) => [a -> a] the list will be the Traversable, and the things inside the list should be Applicative. Therefore, it uses the applicative instance for functions.
So when you apply sequenceA to [(+3),(+2),(+1)], the following computation is built:
sequenceA [(+3),(+2),(+1)] = (:) <$> (+3) <*> sequenceA [(+2),(+1)]
sequenceA [(+2),(+1)] = (:) <$> (+2) <*> sequenceA [(+1)]
sequenceA [(+1)] = (:) <$> (+1) <*> sequenceA []
sequenceA [] = pure []
Let's look at the last line. pure [] takes an empty list and puts it inside some applicative structure. As we've just seen, the applicative structure in this case is ((->) r). Because of this, sequenceA [] = pure [] = const [].
Now, line 3 can be written as:
sequenceA [(+1)] = (:) <$> (+1) <*> const []
Combining functions this way with <$> and <*> results in parallel application. (+1) and const [] are both applied to the same argument, and the results are combined using (:)
Therefore sequenceA [(+1)] returns a function that takes a Num a => a type value, applies (+1) to it, and then prepends the result to an empty list, \x -> (:) ((1+) x) (const [] x) = \x -> [(+1) x].
This concept can be extended further to sequenceA [(+3), (+2), (+1)]. It results in a function that takes one argument, applies all three functions to that argument, and combines the three results with (:) collecting them in a list: \x -> [(+3) x, (+2) x, (+1) x].
it is using instance Applicative ((->) a).
Try this in ghci:
Prelude> :t [(+3),(+2),(+1)]
[(+3),(+2),(+1)] :: Num a => [a -> a]
Prelude> :t sequenceA
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
and pattern match the argument type: t = [], f = (->) a
and the Applicative constraint is on f.
For anyone who has trouble accepting that an argument to sequenceA [(+1)] just magically applies itself to BOTH (+1) and const [], this is for you. It was the only sticking point for me after realizing that pure [] = const [].
sequenceA [(+1)] = (:) <$> (+1) <*> const []
Using lambdas (so we can explicitly show and move things around when we start treating function application like a functor and an applicative):
sequenceA [(+1)] = \b c -> ( (:) b c ) <$> ( \a -> (+1) a ) <*> ( \a -> const [] a )
Both (<$>) and (<*>) are infixl 4. Which means we read and evaluate from left to right, i.e. we start with (<$>).
Where (<$>) :: Functor f => (a -> b) -> f a -> f b.
The effect of <$> is to pluck (+1) out of it's wrapper ((->) r), OR \a -> from our lambda code, and apply it to \b c -> ( (:) b c ) where it will take the place of b, then re-apply the wrapper (that's the \a that appears after the equals sign on the line below):
sequenceA [(+1)] = \a c -> ( (:) ((+1) a) c ) <*> ( \a -> const [] a )
Notice that (:) is still waiting for an argument c, and (+1) is still waiting for an a. Now, we get to the applicative part.
Remember that: (<*>) :: f (a -> b) -> f a -> f b. Our f here is the function application \a ->.
Both sides now have the same wrapper, namely \a ->. I'm keeping the a's in there to remind us where the a's will be applied later, so it does become a little pseudo-y here. The function application will be connected back up in just a jiffy. Both functions depend on the same a, precisely because they had the same function application wrapper i.e. an applicative. Without their \a -> wrappers (thanks to <*>), it goes like this:
( \c -> ( (:) ((+1) a) c ) ) (const [] a)
= ( (:) ((+1) a) (const [] a) ) -- Ignore those a's, they're placeholders.
Now, the very last thing that <*> does is to pop this result back into it's wrapper \a ->:
sequenceA [(+1)] = \a -> ( (:) ((+1) a) (const [] a) )
Sugaring this up a little bit gives:
sequenceA [(+1)] = \a -> (+1) a : const [] a
See! It makes perfect sense that an argument to sequenceA [(+1)] goes to both (+1) and const. Applying a 2, for instance, gives:
sequenceA [(+1)] 2 = (+1) 2 : const [] 2
Remember that const a b :: a -> b -> a, and therefore just ignores it's input:
sequenceA [(+1)] 2 = 3 : []
OR, more sweetly:
sequenceA [(+1)] 2 = [3]

Resources