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

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]

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

Haskell: Understanding the map function when used with lambda function

I have the following two Haskell expressions:
map (\f x -> f x 5) [(-),(+),(*)]
map (\f x -> f 5 x) [(-),(+),(*)]
And I'm trying to figure out whether either expression above is equivalent to the following expression:
map ($ 5) [(-),(+),(*)]
I am trying to understand what the difference between the first two expressions is.
Since for both expressions, there is only one parameter passed to the lambda function (e.g. the operator), the function will be partially applied.
Is it correct to say that the elements in the result list from the first expression will be:
(1) - x 5 = (- x) 5
(2) + x 5 = (+ x) 5
(3) * x 5 = (* x) 5
And for the second expression:
(1) - 5 x = (- 5) x
(2) + 5 x = (+ 5) x
(3) * 5 x = (* 5) x
However, I don't think that either expression is equivalent to map ($ 5) [(-),(+),(*)]. This is because (- x) 5 (where x is a number) gives an error in GHCI and is an invalid expression. Similarly (- 5) x also gives an error.
On the other hand, map ($5) [(-)], results in a function that takes a number and subtracts it from 5.
Is this reasoning correct? Any insights are appreciated.
(- 5) 5 gives out an error because prefix minus is a special case in the language syntax: (- 5) means minus five, the number, and not a function that subtracts five (see also: Currying subtraction). That being so, I will focus on the (+) case, which is not exceptional.
In your second expression, map (\f x -> f 5 x) [(-),(+),(*)], the second element of the result list will be:
(\f x -> f 5 x) (+)
When evaluating such a thing by hand, it is important to be careful to not mix up prefix, infix and sectioned uses of operators. Application here gives out...
\x -> (+) 5 x -- Prefix syntax (note the parentheses around the operator)
... which is equivalent to...
\x -> 5 + x -- Infix syntax
... and to:
\x -> (5 +) x -- Left section
\x -> (+ x) 5 -- Right section
(5 +) -- Left section, pointfree
So the sections, which are patterned after infix usage of the operators, should be the other way around relative to your question. As for map ($ 5) [(-),(+),(*)], it is equivalent to map (\f x -> f 5 x) [(-),(+),(*)], your second expression. You can confirm that by using the fact that ($) f x = f x to figure out what the ($ 5) right section is.

What does the 'outermost part' of expression mean in Haskell

True beginner here, and I'm reading about the differences between NF and WHNF, and one of the definitions I come across states
To determine whether an expression is in weak head normal form, we only have to
look at the outermost part of the expression.
I'm not sure what criteria to apply to determine what the 'outermost' part is. For example (from a stack overflow answer by #hammer):
'h' : ("e" ++ "llo") -- the outermost part is the data constructor (:)
(1 + 1, 2 + 2) -- the outermost part is the data constructor (,)
\x -> 2 + 2 -- the outermost part is a lambda abstraction
Especially in the first example there, the (:) operator is in the middle of the 'h' and the other expression, so how is it the outermost part?
In general, when looking at an expression, how does one determine what the outermost part is?
Good question. Here, "outermost" (or "topmost") describes the location in reference to a kind of standard, abstract view of the expression that can differ from its actual syntax. For example, these two expressions:
(1, 2)
(,) 1 2
have identical meaning in Haskell. It turns out that in both cases, the constructor (,) is the outermost part of the expression, even though the expressions have different syntactic form with the comma appearing in different physical locations in the syntax.
Generally speaking, Haskell's "standard syntax" involves function application of the form:
fexpr expr1 .. exprn
However, the language also allows other kinds of syntax:
1 + 2 -- infix operators
(3, 4) -- tuples
[5,6,7,8] -- lists
"abc" -- strings
These alternate syntaxes can be converted to the standard syntax like so:
1 + 2 ==> (+) 1 2
(3, 4) ==> (,) 3 4
[5,6,7,8] ==> (:) 5 ((:) 6 ((:) 7 ((:) 8 [])))
"abc" ==> (:) 'a' ((:) 'b' ((:) 'c' []))
Though it's far from obvious, (+) is a variable whose value is a function (like sqrt); while (,) and (:) are constructors (just like True or Just). Even more confusing and further from obvious, even though [1,2,3] is special syntax, the empty list [] is a (unary) constructor! That's why I still used empty lists on the right-hand side in my standard syntax versions.
Anyway, once converted to the standard syntax, an expression will either be a constructor application, like one of these:
True -- a nullary constructor
(,) (1+2) (2+3) -- constructor expecting two args and fully applied
(:) 5 -- constructor partially applied and expecting one more arg
and we say that the "outermost part" of the expression is this constructor application, or it will be an unapplied lambda abstraction:
(\x y -> (+) x (length y))
and we say that the "outermost part" of the expression is this unapplied lambda abstraction, or it will be something else:
w -- a variable
(\x -> x) 10 -- an applied lambda abstraction
(f x) y ((*) 2 z) -- some other function application
(+) 10 (length (1:[])) -- another function application
and we say the "outermost part" of the expression is a variable reference or a function application or whatever.
Anyway, if the outermost part is either a constructor application or an unapplied lambda abstraction, then it's said to be in weak head normal form. If it's something else, it's not.
So, Just (5+6) is in WHNF because the outermost part is the application of the constructor Just. On the other hand, sqrt (5+6) is not in WHNF because the outermost part is the application of the variable sqrt, and a variable isn't a constructor.
Similarly, 5+6 itself is not in WHNF because the outermost part is the application of the variable (+) to 5 and 6, while [5,6] is in WHNF because the outermost part is the application of the (implied) constructor (:) to 5 and [6].
You have to look at the abstract syntax tree to understand what this means.
:
/ \
'h' ++
/ \
"e" "llo"
(,)
/ \
+ +
/ \ / \
1 1 2 2
\x ->
|
+
/ \
2 2
"Outermost" means the root of the tree.

Confusion on partially applied infix operators

So I was reading through a Haskell guide online, and was just curious about the combination of infix operators and filter.
Say you have a function like
filter (>5) [6, 10, 5]
That will return [6,10], which seems like the intuitive way filter should work.
However, doing
filter ((>) 5) [6, 10, 5]
returns an empty list (this still makes sense, (>) checks if its first argument is larger than the second argument).
However, filter is typically defined something like
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
When the type system knows it has an infix operator, are most of those infix operators written so that a partially applied function needs a leading argument to the original prefix function? i.e. is infix > defined as something like (butchered syntax)
infix> :: Int -> Int-> Bool
infix> x y = (>) y x
x infix> y = (>) x y
Sorry if this question doesn't make sense, I feel like I'm missing something basic in how p x is evaluated when p is a partially applied infix operator.
(>5) and ((>) 5) are two different types of expression.
The first is what is known as a section. Sections are of the form (op exp) or (exp op) where op is an infix operator and exp is another expression. A section takes an argument and applies it on the missing side, so (>5) 4 = (4 > 5) and (5>) 4 = (5 > 4). In other words, (>5) is equivalent to \x -> x > 5.
In ((>) 5), (>) is the infix operator > converted to an expression. ((>) 5) then is the application of 5 to the function (>), which gives a new function that takes the next argument. If we apply that argument, e.g., (>) 5 4, we get the prefix equivalent of (5 > 4).
This conversion of an infix operator to an expression that can be used prefix works for all infix operators. You can also go the other way and covert an identifier into an infix operator, i.e.:
`foo`
You can even say:
(`foo`)
to turn it back into an expression.

Partial Application with Infix Functions

While I understand a little about currying in the mathematical sense, partially
applying an infix function was a new concept which I discovered after diving
into the book Learn You a Haskell for Great Good.
Given this function:
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
The author uses it in a interesting way:
ghci> applyTwice (++ [0]) [1]
[1,0,0]
ghci> applyTwice ([0] ++) [1]
[0,0,1]
Here I can see clearly that the resulting function had different parameters
passed, which would not happen by normal means considering it is a curried
function (would it?). So, is there any special treatment on infix sectioning by
Haskell? Is it generic to all infix functions?
As a side note, this is my first week with Haskell and functional programming,
and I'm still reading the book.
Yes, you can partially apply an infix operator by specifying either its left or right operand, just leaving the other one blank (exactly in the two examples you wrote).
So, ([0] ++) is the same as (++) [0] or \x -> [0] ++ x (remember you can turn an infix operator into a standard function by means of parenthesis), while (++ [0]) equals to \x -> x ++ [0].
It is useful to know also the usage of backticks, ( `` ), that enable you to turn any standard function with two arguments in an infix operator:
Prelude> elem 2 [1,2,3]
True
Prelude> 2 `elem` [1,2,3] -- this is the same as before
True
Prelude> let f = (`elem` [1,2,3]) -- partial application, second operand
Prelude> f 1
True
Prelude> f 4
False
Prelude> let g = (1 `elem`) -- partial application, first operand
Prelude> g [1,2]
True
Prelude> g [2,3]
False
Yes, this is the section syntax at work.
Sections are written as ( op e ) or ( e op ), where op is a binary operator and e is an expression. Sections are a convenient syntax for partial application of binary operators.
The following identities hold:
(op e) = \ x -> x op e
(e op) = \ x -> e op x
All infix operators can be used in sections in Haskell - except for - due to strangeness with unary negation. This even includes non-infix functions converted to infix by use of backticks. You can even think of the formulation for making operators into normal functions as a double-sided section:
(x + y) -> (+ y) -> (+)
Sections are (mostly, with some rare corner cases) treated as simple lambdas. (/ 2) is the same as:
\x -> (x / 2)
and (2 /) is the same as \x -> (2 / x), for an example with a non-commutative operator.
There's nothing deeply interesting theoretically going on here. It's just syntactic sugar for partial application of infix operators. It makes code a little bit prettier, often. (There are counterexamples, of course.)

Resources