Take the 2-minute tour ×
import Control.Applicative
import Control.Arrow

filter ((&&) <$> (>2) <*> (<7)) [1..10]  
filter ((>2) &&& (<7) >>> uncurry (&&)) [1..10]

Both get the same result! However, it is VERY difficult for me to understand. Could someone here explain it in detail?

share|improve this question
Where do these examples come from? –  Karl Knechtel Jun 9 '11 at 3:33
Applicatives really need their own syntax sugar, both for regular and infix application. filter ((>2) <(&&)> (<7)) [1..10] would read very nicely. –  pelotom Jun 9 '11 at 3:44
@pelotom: There's always idiom brackets. We have monad comprehensions now, why not applicative comprehensions? :) –  C. A. McCann Jun 9 '11 at 3:58
For arrows there is a nice explantaion in Wikibooks: en.wikibooks.org/wiki/Haskell/Understanding_arrows –  Landei Jun 9 '11 at 6:53
@Karl Knechtel I think it stems from this answer to an earlier question. –  yatima2975 Jun 9 '11 at 15:09

1 Answer 1

Let's start with the second, which is simpler. We have two mysterious operators here, with the following types:

(&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
(>>>) :: Category cat => cat a b -> cat b c -> cat a c

The Arrow and Category type classes are mostly about things that behave like functions, which of course includes functions themselves, and both instances here are just plain (->). So, rewriting the types to use that:


The second has a very similar type to (.), the familiar function composition operator; in fact, they're the same, just with arguments swapped. The first is more unfamiliar, but the types again tell you all you need to know--it takes two functions, both taking an argument of a common type, and produces a single function that gives the results from both combined into a tuple.

So, the expression (>2) &&& (<7) takes a single number and produces a pair of Bool values based on the comparisons. The result of this is then fed into uncurry (&&), which just takes a pair of Bools and ANDs them together. The resulting predicate is used to filter the list in the usual manner.

The first one is more cryptic. We have two mysterious operators, again, with the following types:


Observe that the second argument of (<$>) in this case is (>2), which has type (Ord a, Num a) => a -> Bool, while the type of (<$>)'s argument has type f a. How are these compatible?

The answer is that, just as we could substitute (->) for a and cat in the earlier type signatures, we can think of a -> Bool as (->) a Bool, and substitute ((->) a) for the f. So, rewriting the types, using ((->) t) instead to avoid clashing with the other type variable a:

(<$>) :: (a -> b) -> ((->) t) a -> ((->) t) b
(<*>) :: ((->) t) (a -> b) -> ((->) t) a -> ((->) t) b

Now, putting things back in normal infix form:

(<$>) :: (a -> b) -> (t -> a) -> (t -> b)
(<*>) :: (t -> (a -> b)) -> (t -> a) -> (t -> b)

The first turns out to be function composition, as you can observe from the types. The second is more complicated, but once more the types tell you what you need--it takes two functions with an argument of a common type, one producing a function, the other producing an argument to pass to the function. In other words, something like \f g x -> f x (g x). (This function also happens to be known as the S combinator in combinatory logic, a subject explored extensively by the logician Haskell Curry, whose name no doubt seems strangely familiar!)

The combination of (<$>) and (<*>) sort of "extends" what (<$>) alone does, which in this case means taking a function with two arguments, two functions with a common argument type, applying a single value to the latter two, then applying the first function to the two results. So ((&&) <$> (>2) <*> (<7)) x simplifies to (&&) ((>2) x) ((<7) x), or using normal infix style, x > 2 && x < 7. As before, the compound expression is used to filter the list in the usual manner.

Also, note that while both functions are obfuscated to some degree, once you get used to the operators used, they're actually quite readable. The first abstracts over a compound expression doing multiple things to a single argument, while the second is a generalized form of the standard "pipeline" style of stringing things together with function composition.

Personally I actually find the first one perfectly readable. But I don't expect most people to agree!

share|improve this answer
thanks for your answer! I makes me much clear ! –  z_axis Jun 9 '11 at 5:14
+1: You explained my code much better than I could. –  Landei Jun 9 '11 at 6:53
I would add that Haskellers don't do the type gymnastics demonstrated here in their heads every time. Instead, the pattern: f <$> x <*> y (also spelled: liftA2 f x y) is well-known. It means: Apply the function f on two Applicative-wrapped values. Functions can be viewed as "wrapped values": (>2) and (<7) can be seen as wrapped Bools, where Num a => ((->) a) is the "wrapper". The function (&&) can thus be applied on two "wrapped" bools to yield the result wrapped bool. Same can be used to defined: avg = liftA2 (/) sum length –  Peaker Jun 10 '11 at 1:07
@Peaker: Quite true, and good to emphasize. The breakdown I walked through serves to build intuition and understanding, after which the abstraction can be read directly without expanding the definitions, with very common abstractions eventually becoming as natural as the pieces they're built from. –  C. A. McCann Jun 10 '11 at 18:50

Your Answer


