Infix function evaluation with $ - haskell

$ 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.

Related

How to incorporate $ in a given expression?

I want to write an expression which will give a list that is equal to the list comprehension [x|x<-[1..100], x`mod`7==0], but I'm asked by my teacher to use $ in this program.
So, how could I use $ in here?
PS: I'm new to Haskell, so would prefer easy expressions, please.
($) is in an infix operator with a type signature
($) :: (a -> b) -> a -> b
which means it takes two parameters, first a function (a -> b) (on the left) which accepts a single parameter, a value of type designated by the type variable a. The second parameter of ($) (on the right) is a single value again designated by the type variable a. Then the ($) operator simply applies it's second parameter to the first parameter. So for an example (+2) $ 3 would give us 5.
So if you insist on doing list comprehensions you may do as follows in point-free style;
Prelude> [x|x<-[1..100], (== 0) . mod x $ 7]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
or in a more straightforward fashion
Prelude> filter ((==0) . (`mod` 7)) $ take 100 [1..]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
$ just means "take whatever is on the right, and pass it as argument to the left".
So for example :
map (`mod`7) (take 100 [1..])
map (`mod`7) $ take 100 [1..]
Those two lines are the same, the $ just means you can avoid the parenthesis around the second call.
The take is useless but I didn't have a better idea for a simple example :)

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.

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

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.

How to use the ($) operator correctly

These lines execute correctly:
Prelude> 1 / (1 + 1)
0.5
Prelude> (/) 1 $ (+) 1 1
0.5
Prelude> (/) 1 $ 1 + 1
0.5
This one does not:
Prelude> 1 / $ (+) 1 1
<interactive>:1:4: parse error on input `$'
Why?
/ is an infix operator. It requires valid expression on both its sides. 1 is a literal and thus a valid expression. However, on right-hand side you have immediately another infix operator, which requires to be preceded by another valid expression (and 1 / is not a valid expression, as it lacks right-hand side argument to the / operator). This is why parser reports error (invalid grammar — see haskell report for ugly details ;)
I believe that it is because $ is an operator that requires a function preceding it. The expression 1 / in your last example does not evaluate to a function. In that case, the parser is expecting to find a (numeric) expression as the second argument to the / operator.

Haskell function composition (forward pipe) - why does this work?

In the below code, fibseq represents a sequence of numbers from the Fibonacci sequence.
(from code to solve Project Euler #2)
I have defined an infix function |>:
(|>) x y = y x.
This lets me do the following (like a unix pipeline):
take 34 fibseq |> filter even |> filter (< 4000000) |> sum
My question is, why does this work?
I would have thought that take 34 fibseq |> filter even ought to transform into filter (take 34 fibseq) even, which (I think) would lead to a type error.
Instead it seems to be transforming into filter even (take 34 fibseq) which works and is what I want, but I don't understand why it's working.
Function application (like filter even) binds tighter than any operators, so your code is equivalent to:
(take 34 fibseq) |> (filter even) |> (filter (< 4000000)) |> sum
This works because of operator precedence. The function application operator, juxtaposition or (the space), has the highest precedence, so take 34 fibseq |> filter even parses as ((take 34) fibseq) |> (filter even), which is equivalent to (filter even) ((take 34) fibseq); since function application is left-associative, this is then equivalent to filter even (take 34 fibseq).
In general, any binary operator can be given a precedence with a fixity declaration, such as
infixl 0 |>
infixr 9 .
The l or r says whether the operation is left- or right-associative (that is, whether a • b • c groups as (a • b) • c or a • (b • c)); the number—an integer between 0 and 9—specifies the precedence level. Higher numbers mean higher precedence (with application having an effective precedence of ∞); for instance, * and / have precedence 7, and + and - have precedence 6. To check the precedence of an operator in ghci, just type :info $ (or whichever operator) at the prompt.
And just as a note: your code will work, but it's not how I would typically write it. If you're curious, in Haskell, I would write that code with the $ operator, which just performs function application but is low precedence: filter even $ take 34 fibseq. If I had more functions to apply, I would use the composition operator: fun1 arg1 . fun2 . fun3 arg2 arg3 . filter even $ take 34 fibseq. It reads the other way, but it's what you typically find in Haskell.

Resources