Why is `($ 4) (> 3)` equivalent to `4 > 3`? - haskell

I noticed as I was playing around with Haskell today that it is possible to do something like
($ 4) (> 3)
which yields True. What is going on here? It'd be great to have some intuition.
My guess? It looks like the ($ 4) is an incomplete function application, but where I'm confused is that $ is an infix operator, so shouldn't it look like (4 $)? This doesn't compile, so clearly not, which leads me to believe that I don't really understand what's going on. The (>3) term makes sense to me, because if you supply something like (\x -> x 4) (>3), you end up with the same result.

($ 4) is what's called a section. It's a way of partially applying an infix operator, but providing the right-hand side instead of the left. It's exactly equivalent to (flip ($) 4).
Similarly, (> 3) is a section.
($ 4) (> 3)
can be rewritten as
(flip ($) 4) (> 3)
which is the same as
flip ($) 4 (> 3)
which is the same as
(> 3) $ 4
And at this point, it should be clear that this boils down to (4 > 3).

You can partially apply an infix operator from either side. For commutative operators such as +, it doesn't matter if you say (+ 1) or (1 +), but for example for division you can supply either the dividend (5 /) or the divisor (/ 5).
The function application operator takes a function as the left-hand operand and a parameter as the right-hand operand (f $ x), so you can partially apply it either with a function (f $) or with a parameter ($ x). So given
($ 4) (> 3)
You first partially apply the $-operator with the parameter 4 and supply it with the function (> 3). So what this essentially becomes is
(> 3) $ 4
Which is the same as (4 > 3).

($ 4) is the function that takes a function and applies 4 to it.
(> 3) is the function that takes a number and checks if it is greater than 3.
So by giving the latter function to the former, you are essentially applying 4 to the function that checks if its input is greater than 3, and thus you get True.

Related

Haskell: Understanding function application operator when used with map function

I have the following Haskell expression:
map ($ 5) [(-),(+),(*)]
I know the function application operator ($) applies a function to a given parameter. However since the (-), (+) and (*) functions take two parameters, by applying these functions to 5 through map, the functions are partially applied.
The resulting list will contain three functions that takes another parameter and:
(1) Subtracts the parameter from 5
(2) Adds the parameter to 5
(3) Multiplies the parameter by 5
However is it valid to say that the above expression is equivalent to the following?
[(5 -),(5 +),(5 *)]
I think this is correct, since I checked the types of (5 -), (5 +) and (5 *) in GHCI, and they are all functions that take a number and return a number:
(5 -) :: Num a => a -> a
(5 +) :: Num a => a -> a
(5 *) :: Num a => a -> a
Any insights are appreciated.
Correct; you can also apply the operators a second time via:
map ($4) $ map ($ 5) [(-),(+),(*)]
producing [5-4, 5 + 4, 5 * 4]
Also, you can specify the arguments to the right of the operator, giving the same result:
[((-) 5),(+ 5),(* 5)]
(The reason the (-) 5 has the "-" parenthesized, is to prevent the compiler to think you mean "minus five", a negative number, the usual interpretation of (- 5)).

Why (-2) is different from (\x -> x - 2) in Haskell? [duplicate]

This question already has an answer here:
Why doesn't `-` (minus) work for operator sections? [duplicate]
(1 answer)
Closed 4 years ago.
I'm learning Haskell using CIS194(spring13) by myself. Today when I was trying to deal with homework 4 Exercise 1, I got a error with
fun1' :: [Integer] -> Integer
fun1' = foldl' (*) 1 . map (-2) . filter even
It's said:
error:
? No instance for (Num (Integer -> Integer))
arising from a use of syntactic negation
(maybe you haven't applied a function to enough arguments?)
? In the first argument of map, namely (- 2)
In the first argument of (.), namely map (- 2)
In the second argument of (.), namely map (- 2) . filter even
|
12 | fun1' = foldl' (*) 1 . map (- 2) . filter even
| ^^^
And It's OK to replace (-2) with (\x -> x - 2). I think it just like filter (==0) or map (*3) xs, (-2) should be a function with type signature Integer -> Integer and has same effect with (\x -> x - 2).
So my question is why they are different?
Haskell has a special case in its syntax for -; it is treated as a unary operator, synonymous with negate, whenever that parses. It was considered at the time the language was made that negative numbers would be more commonly needed than subtraction sections (and this still seems true today).
However, it was known that people would occasionally want what you do, and so provisions were made: the Prelude includes a function named subtract which just flips the arguments to (-).
> map (subtract 2) [1,2,3]
[-1,0,1]

Infix function evaluation with $

$ is an infix operator with the lowest possible precedence:
f $ a = f a
Does this not mean that, in the expression below, the part
$ 2 ^ 2
should be evaluated first and then add $ 2? It appears 2 + 2 is evaluated first
Prelude> (2^) $ 2 + 2
returns :
16
No. Try to think of precedence not as being about what gets "evaluated first", and more about where parentheses are inserted.
The fact that $ has the lowest precedence means that parentheses are inserted around everything to the right of it (and, separately, to the left of it, if needed, but they aren't needed here). So
(2^) $ 2 + 2
is equivalent to
(2^) $ (2 + 2)
which is of course
(2^) 4 (i.e. 16)
Precedence rules can be confusing, but I like to think of it as "lower precedence" means "do later". Since $ has the lowest precedence (for example, below (+)), it is performed after (+). Thus (2^) $ 2 + 2 evaluates (2^) to a partially applied function, then evaluates 2+2 to 4, then applies 4 to 2^ to get 16.

I'm confused by Haskell's lazy evaluation

I'm concerned about efficiency in Haskell's lazy evaluation.
consider following code
main = print $ x + x
where x = head [1..]
here, x first hold the expression of head [1..] instead of the result 1, due to the laziness,
but then when I call x + x, will the expression head [1..] be executed twice?
I found the following description on haskell.org
Lazy evaluation, on the other hand, means only evaluating an expression when its results are needed (note the shift from "reduction" to "evaluation"). So when the evaluation engine sees an expression it builds a thunk data structure containing whatever values are needed to evaluate the expression, plus a pointer to the expression itself. When the result is actually needed the evaluation engine calls the expression and then replaces the thunk with the result for future reference.
So does this mean that, in x + x, when calling the first x, head [1..] is executed and x is re-assigned to 1, and the second x is just calling a reference of it?
Did I understand this right?
This is more of a question about particular Haskell implementations than about Haskell itself, since the language makes no particular guarantees about how things are evaluated.
But in GHC (and most other implementations, as far as I'm aware): yes, when thunks are evaluated they are replaced by the result internally, so other references to the same thunk benefit from the work done evaluating it the first time.
The caveat is that there are no real guarantees about which expressions end up implemented as references to the same thunk. The compiler is in general allowed to make whatever transformations to your code it likes so long as the result is the same. Of course, the reason to implement code transformations in a compiler is usually to try to make the code faster, so it's hopefully not likely to rewrite things in such a way as to make it worse, but it can never be perfect.
In practice though, you're usually pretty safe assuming that whenever you give an expression a name (as in where x = head [1..]), then all uses of that name (within the scope of the binding) will be references to a single thunk.
At first, x is just a thunk. You can see that as follows:
λ Prelude> let x = head [1..]
λ Prelude> :sprint x
x = _
Here the _ indicates that x has not yet been evaluated. Its mere definition is recorded.
Then, you can understand how x + x is constructed by just realizing that x is a pointer to this thunk: both those x will point to the same thunk. Once one is evaluated, the other is, since it's the same thunk.
You can see that with ghc-vis:
λ Prelude> :vis
λ Prelude> :view x
λ Prelude> :view x + x
should show you something along the lines of:
Here you can see that the x + x thunk actually points twice to the x thunk.
Now, if you evaluate x, by printing it for example:
λ Prelude> print x
You'll obtain:
You can see here that the x thunk is no longer a thunk: it's the value 1.
There are two ways to evaluate an expression:
Lazy (evaluate outermost first).
Strict (evaluate innermost first).
Consider the following function:
select x y z = if x > z then x else y
Now let's call it:
select (2 + 3) (3 + 4) (1 + 2)
How will this be evaluated?
Strict evaluation: Evaluate innermost first.
select (2 + 3) (3 + 4) (1 + 2)
select 5 (3 + 4) (1 + 2)
select 5 7 (1 + 2)
select 5 7 3
if 5 > 3 then 5 else 7
if True then 5 else 7
5
Strict evaluation took 6 reductions. To evaluate select we first had to evaluate its arguments. In strict evaluation the arguments to a function are always fully evaluated. Hence functions are "call by value". Thus there's no extra bookkeeping.
Lazy evaluation: Evaluate outermost first.
select (2 + 3) (3 + 4) (1 + 2)
if (2 + 3) > (1 + 2) then (2 + 3) else (3 + 4)
if 5 > (1 + 2) then 5 else (3 + 4)
if 5 > 3 then 5 else (3 + 4)
if True then 5 else (3 + 4)
5
Lazy evaluation only took 5 reductions. We never used (3 + 4) and hence we never evaluated it. In lazy evaluation we can evaluate a function without evaluating its arguments. The arguments are only evaluated when needed. Hence functions are "call by need".
However "call by need" evaluation strategies need extra bookkeeping - you need to keep a track of whether an expression has been evaluated. In the above expression when we evaluate x = (2 + 3) we don't need to evaluate it again. However we do need to keep a track of whether it was evaluated.
Haskell supports both strict and lazy evaluation. However it supports lazy evaluation by default. To enable strict evaluation you would have to use the special seq and deepSeq functions.
Similarly you can have lazy evaluation in strict languages like JavaScript. However you would need to keep a track of whether an expression has been evaluated or not. You could research about implementing thunks in JavaScript or similar languages.

Currying subtraction

If we want to map a function that increases every element of a range by 1, we could write
map (\x -> x + 1) [1..5]
but I guess most people would just go for
map (+1) [1..5]
instead. But this obviously doesn't work with (-1) since that's negative one.
So the first thing that came to mind was
map (+(-1)) [1..5]
which would make sense considering how subtraction is defined in the Prelude (x - y = x + negate y), but looks a bit odd to me. I then I came up with
map (flip (-) 1) [1..5]
This somehow looks better to me, but is maybe a bit too complicated.
Now I know this no big deal, but I'm wondering if I'm missing a more obvious way to write this? If not, which of the 2 ways would you prefer? I'm really just asking because often it's small details like this that make your code more idiomatic and hence pleasant for other developers who have to read it.
Solution
Now that I got a couple of answers, I think my personal favorite is
map (subtract 1) [1..5]
followed by
map pred [1..5]
mostly because the first one is really explicit and nobody needs to guess/look up what pred means (predecessor).
You can use the subtract function instead of - if you want to right-section subtraction:
map (subtract 1) [1..5]
Since - is both the infix subtract and the prefix negate, you can't use the (*x) (where * is an infix operator and x a value) syntax for -. Luckily Prelude comes with negate and subtract, which is \x -> -x and \x y -> y-x respectively, so that you may use those where you need to differentiate between the two.
After many years since this question was asked, in GHC 9 we now have
the LexicalNegation extension which allows the section (- 1), as long we use whitespace to separate the minus sign from the number.
Indeed, after enabling the extension, we have:
> map (subtract 1) [1..5] -- still works, of course
[0, 1, 2, 3, 4]
> map (- 1) [1..5] -- with whitespace
[0, 1, 2, 3, 4] -- (- 1) is now a section
> map (-1) [1..5] -- no whitespace
*error* -- (-1) is now a negative literal
I think map (\x -> x - 1) [1..5] transmits the programmer's intention better, since there's no doubt about what is being subtracted from what. I also find your first solution, map (+(-1)) [1..5], easy to read too.
I don't like subtract because it's confusingly backwards. I'd suggest
minus :: Num n => n -> n -> n
minus = (-)
infixl 6 `minus`
Then you can write
map (`minus` 1) [1..5]

Resources