But the actual firstThat function firstThat to be defined differently than its type declaration, with one argument. Since foldr usually takes the three arguments that I put together, some kind of partial application happens.
You're right. However, there is a better way to do this than talk about the “missing arguments” - one that does not make you ask where they went. Here are two ways in which arguments are missing.
First, consider this function:
add :: Num a => a -> a -> a add xy = x + y
As you know, we can also define it as follows:
add :: Num a => a -> a -> a add = (+)
This works because Haskell functions are values, just like any other. We can simply define the add value as equal to another (+) value, which is simply a function. There is no special syntax required to declare a function. The result is that writing arguments is explicitly (almost) never required; the main reason why we do this is because it often makes the code more readable (for example, I could define firstThat without writing the parameter f explicitly, but I won’t do it because the result is pretty disgusting).
Secondly, whenever you see a function type with three arguments ...
firstThat :: (a -> Bool) -> a -> [a] -> a
... you can also read it like this ...
firstThat :: (a -> Bool) -> (a -> [a] -> a)
... that is, a function of one argument, creating a function of two arguments. This works for all functions of more than one argument. The key conclusion is that, at the heart of everything, all Haskell functions take only one argument. This is why a partial application works. So seeing ...
firstThat :: (a -> Bool) -> a -> [a] -> a firstThat f = foldr (\x acc -> if fx then x else acc)
... you can say for sure that you explicitly specified all the parameters that firstThat accepts - that is, only one :)
The lambda expression provided as an argument to foldr does not seem to contain its arguments either.
Not really. foldr (when limited to lists) ...
foldr :: (a -> b -> b) -> b -> [a] -> b
... and therefore the function passed to it takes two arguments (feel free to add air quotes around the "two", given the discussion above). Lambda was written as ...
\x acc -> if fx then x else acc
... with two explicit arguments x and acc .