Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function application in Haskell

OK, it's been a long day and my brain may not function at Haskell level, but I just cannot understand one example from 'Learn You a Haskell'.

The section is called Function Application with $, and there is example of how $ may be defined:

($) :: (a -> b) -> a -> b
f $ x = f x

So far everything is clear. I understand all examples in the section, except for the last one:

ghci> map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]

Here we map ($ 3) across list of functions and get result of application of those functions to 3. But how is this possible?

From the first code snippet it's clear that first argument is a function, we can even write:

*Main> ($) sqrt 4
2.0

Now ($ 3) is a partial application of function $, but 3 goes on function's position! So 3 is supposed to be a function or what?

There is another mystery: what the heck is (4+)? I know that (+4) is a partial application of function +, so (4+) should be partial application of function 4? Nonsense. What sort of trick works here?

like image 546
Mark Karpov Avatar asked Sep 08 '14 14:09

Mark Karpov


People also ask

What is function application Haskell?

"Function application" here just means more or less the same thing as "passing an argument to the function". For example, if you have a function f :: Int -> Int and an x :: Int then f x :: Int is an expression where the expression x is "applied" as an argument to f *.

What are function types in Haskell?

Haskell has first-class functions : functions are values just like integers, lists, etc. They can be passed as arguments, assigned names, etc. … val is value of type Int , and half_of is a value of type Float -> Float .

What does () mean in Haskell?

() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .


2 Answers

($ 3) and (+ 4) aren't partial applications - they're operator sections. A partial application would look like (($) 3) or ((+) 4).

An operator section of the form (? x) (where ? stands for an arbitrary infix operator) binds the right operand of the operator, i.e. it is equivalent to \y -> y ? x. Likewise the operator section (x ?) binds the left operand and is thus equivalent to partial application.

like image 199
sepp2k Avatar answered Sep 25 '22 08:09

sepp2k


I think what's tripping you up is operator sections. These let you partially apply an operator with either one of its arguments, so you can have the operators (+4) and (4+), where 4 is the the second then the first argument to + respectively. A more clear example might be ("Hello" ++) versus (++ "world"), the former prepends "Hello" onto the front of a string, while the latter appends "world" onto the end of a string.

This is contrasted with using operators in prefix form with just parens around it. In this form, the following are equivalent:

> let join = (++)
> join "Hello, " "world"
"Hello, world"
> (++) "Hello, " "world"
"Hello, world"

In prefix form, you treat the operator as a normal function and it accepts its first then second argument in order. In operator sections, it matters which side of the operator the argument is on.


So in your example, you have the partial application of ($ 3), you can reduce it as

map ($ 3) [(4+), (10*), (^2), sqrt]
[($ 3) (4+), ($ 3) (10 *), ($ 3) (^ 2), ($ 3) sqrt]
[4 + 3, 10 * 3, 3 ^ 2, sqrt 3]
[7.0, 30.0, 9.0, 1.7320508075688772]
like image 29
bheklilr Avatar answered Sep 22 '22 08:09

bheklilr