Haskell: Understanding the map function when used with lambda function - haskell

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.

Related

Treating "$" as function application

I encountered this example while reading Learn You a Haskell for Great Good.
ghci> map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
I don't quite see how to treat $ as function application. Does that mean $ is an operator? But if so, how it will be nested with + or * in the example? I tried $ 3 4+, $ 4 + 3, but both raised parse error on input ‘$’. How to think of an expression like this in functional programming context?
$ is indeed an operator, defined as:
f $ x = f x
-- or equivalently:
($) f x = f x
Your expression above is equivalent (by the definition of map) to:
[($ 3) (4 +), ($ 3) (10 *), ($ 3) sqrt]
The parentheses in ($ 3) and (4 +) are not optional. They're part of what's called an operator section. Basically, there are four ways you can use an infix operator (such as +):
Between two arguments:
x + y
Only giving the first argument:
(x +)
-- like \y -> x + y
Only giving the second argument:
(+ y)
-- like \x -> x + y
No arguments:
(+)
-- like \x y -> x + y
($ 3) f evaluates to f $ 3 evaluates to f 3.
($ 3) (4 +) evaluates to (4 +) $ 3 evaluates to (4 +) 3 evaluates to 4 + 3 evaluates to 7.

Confusion about the $ operator and parentheses

I'm working my way through the first haskell book and struggle with the $ operator:
The following line works:
map (>= 16) . take 5 $ iterate (\x -> x^2) 2
However, the following doesn't:
map (>= 16) . take 5 (iterate (\x -> x^2) 2)
Possible cause: `take' is applied to too many arguments
I don't see the problem here. take takes an int and a list. To my understanding, I provided both arguments.
What do I have to do if I want to avoid the $ operator?
The ($) :: (a -> b) -> a -> b operator is a function that simply has a the lowest priority (infixr 0, only ($!) and seq have the same priority). As a result:
map (>= 16) . take 5 $ iterate (\x -> x^2) 2
is equivalent to:
(map (>= 16) . take 5) (iterate (\x -> x^2) 2)
so also with brackets for the left operand as well.
It is actually a nice thing about Haskell that you can use operators as a grouping mechanism: ($) is simply defined as ($) f x = f x, but because of the fact that it is an operator, it can be used as a way to avoid brackets.

How is $ used in higher order functions ? [duplicate]

This question already has answers here:
Why is `($ 4) (> 3)` equivalent to `4 > 3`?
(3 answers)
Closed 7 years ago.
This concerns an example encountered in Learn you a Haskell for Great Good, namely this one :
ghci> map ($ 3) [(4+), (10*), (^2), sqrt]
I'm trying to understand it but it makes no sense to me. Of course, the list of functions will be applied to the input (number 3) but I don't see how the $ operator helps. I'm trying to trace the order of application of things (if there's a haskell IDE with a step through compiler please let me know) and can't understand how $ being right associative allows flipping the function application, ie when I see map like this
map fun [1, 2 .. n]
I imagine the following happening to form the output list
fun 1
fun 2
.
.
fun n
but for the example at hand, how is this of meaning :
$3 4+
how is this of meaning :
$3 4+
That's not actually of meaning, indeed. But that's not what it simplifies to! It simplifies to
($3) (4+)
These things are operator sections.
($ 3) ≡ \x -> x $ 3
(4+) ≡ \x -> 4 + x
(10*) ≡ \x -> 10*x
(^2) ≡ \x -> x^2
so
($3) (4+) ≡ (\f -> f $ 3) (\y -> 4 + y)
≡ (\y -> 4 + y) $ 3
≡ (\y -> 4 + y) 3
≡ 4 + 3
Perhaps it's easier to understand if you visualise the “holes”:
map (□ $ 3) [(4+□), (10*□), (□^2), sqrt □]
≡ [(4+□) $ 3, (10*□) $ 3, (□^2) $ 3, (sqrt □) $ 3]
≡ [(4+3), (10*3), (3^2), (sqrt 3)]
The operator $ calls the function which is its left hand argument on the value which is its right hand argument. In the use of the example it "puts" the value 3 as additional argument of the sections in the list
Thus ($ 3) (4+) is (4+3). Analogously ($ 2) (4/) is (4/2)
The use of sections is easier to grasp using normal arithmetic operations. For instance: (/2) 4 is the same as 4/2 and thus 2

Partial application of functions and currying, how to make a better code instead of a lot of maps?

I am a beginner at Haskell and I am trying to grasp it.
I am having the following problem:
I have a function that gets 5 parameters, lets say
f x y w z a = x - y - w - z - a
And I would like to apply it while only changing the variable x from 1 to 10 whereas y, w, z and a will always be the same. The implementation I achieved was the following but I think there must be a better way.
Let's say I would like to use:
x from 1 to 10
y = 1
w = 2
z = 3
a = 4
Accordingly to this I managed to apply the function as following:
map ($ 4) $ map ($ 3) $ map ($ 2) $ map ($ 1) (map f [1..10])
I think there must be a better way to apply a lot of missing parameters to partially applied functions without having to use too many maps.
All the suggestions so far are good. Here's another, which might seem a bit weird at first, but turns out to be quite handy in lots of other situations.
Some type-forming operators, like [], which is the operator which maps a type of elements, e.g. Int to the type of lists of those elements, [Int], have the property of being Applicative. For lists, that means there is some way, denoted by the operator, <*>, pronounced "apply", to turn lists of functions and lists of arguments into lists of results.
(<*>) :: [s -> t] -> [s] -> [t] -- one instance of the general type of <*>
rather than your ordinary application, given by a blank space, or a $
($) :: (s -> t) -> s -> t
The upshot is that we can do ordinary functional programming with lists of things instead of things: we sometimes call it "programming in the list idiom". The only other ingredient is that, to cope with the situation when some of our components are individual things, we need an extra gadget
pure :: x -> [x] -- again, one instance of the general scheme
which wraps a thing up as a list, to be compatible with <*>. That is pure moves an ordinary value into the applicative idiom.
For lists, pure just makes a singleton list and <*> produces the result of every pairwise application of one of the functions to one of the arguments. In particular
pure f <*> [1..10] :: [Int -> Int -> Int -> Int -> Int]
is a list of functions (just like map f [1..10]) which can be used with <*> again. The rest of your arguments for f are not listy, so you need to pure them.
pure f <*> [1..10] <*> pure 1 <*> pure 2 <*> pure 3 <*> pure 4
For lists, this gives
[f] <*> [1..10] <*> [1] <*> [2] <*> [3] <*> [4]
i.e. the list of ways to make an application from the f, one of the [1..10], the 1, the 2, the 3 and the 4.
The opening pure f <*> s is so common, it's abbreviated f <$> s, so
f <$> [1..10] <*> [1] <*> [2] <*> [3] <*> [4]
is what would typically be written. If you can filter out the <$>, pure and <*> noise, it kind of looks like the application you had in mind. The extra punctuation is only necessary because Haskell can't tell the difference between a listy computation of a bunch of functions or arguments and a non-listy computation of what's intended as a single value but happens to be a list. At least, however, the components are in the order you started with, so you see more easily what's going on.
Esoterica. (1) in my (not very) private dialect of Haskell, the above would be
(|f [1..10] (|1|) (|2|) (|3|) (|4|)|)
where each idiom bracket, (|f a1 a2 ... an|) represents the application of a pure function to zero or more arguments which live in the idiom. It's just a way to write
pure f <*> a1 <*> a2 ... <*> an
Idris has idiom brackets, but Haskell hasn't added them. Yet.
(2) In languages with algebraic effects, the idiom of nondeterministic computation is not the same thing (to the typechecker) as the data type of lists, although you can easily convert between the two. The program becomes
f (range 1 10) 2 3 4
where range nondeterministically chooses a value between the given lower and upper bounds. So, nondetermism is treated as a local side-effect, not a data structure, enabling operations for failure and choice. You can wrap nondeterministic computations in a handler which give meanings to those operations, and one such handler might generate the list of all solutions. That's to say, the extra notation to explain what's going on is pushed to the boundary, rather than peppered through the entire interior, like those <*> and pure.
Managing the boundaries of things rather than their interiors is one of the few good ideas our species has managed to have. But at least we can have it over and over again. It's why we farm instead of hunting. It's why we prefer static type checking to dynamic tag checking. And so on...
Others have shown ways you can do it, but I think it's useful to show how to transform your version into something a little nicer. You wrote
map ($ 4) $ map ($ 3) $ map ($ 2) $ map ($ 1) (map f [1..10])
map obeys two fundamental laws:
map id = id. That is, if you map the identity function over any list, you'll get back the same list.
For any f and g, map f . map g = map (f . g). That is, mapping over a list with one function and then another one is the same as mapping over it with the composition of those two functions.
The second map law is the one we want to apply here.
map ($ 4) $ map ($ 3) $ map ($ 2) $ map ($ 1) (map f [1..10])
=
map ($ 4) . map ($ 3) . map ($ 2) . map ($ 1) . map f $ [1..10]
=
map (($ 4) . ($ 3) . ($ 2) . ($ 1) . f) [1..10]
What does ($ a) . ($ b) do? \x -> ($ a) $ ($ b) x = \x -> ($ a) $ x b = \x -> x b a. What about ($ a) . ($ b) . ($ c)? That's (\x -> x b a) . ($ c) = \y -> (\x -> x b a) $ ($ c) y = \y -> y c b a. The pattern now should be clear: ($ a) . ($ b) ... ($ y) = \z -> z y x ... c b a. So ultimately, we get
map ((\z -> z 1 2 3 4) . f) [1..10]
=
map (\w -> (\z -> z 1 2 3 4) (f w)) [1..10]
=
map (\w -> f w 1 2 3 4) [1..10]
=
map (\x -> ($ 4) $ ($ 3) $ ($ 2) $ ($ 1) $ f x) [1..10]
In addition to what the other answers say, it might be a good idea to reorder the parameters of your function, especially x is usually the parameter that you vary over like that:
f y w z a x = x - y - w - z - a
If you make it so that the x parameter comes last, you can just write
map (f 1 2 3 4) [1..10]
This won't work in all circumstances of course, but it is good to see what parameters are more likely to vary over a series of calls and put them towards the end of the argument list and parameters that tend to stay the same towards the start. When you do this, currying and partial application will usually help you out more than they would otherwise.
Assuming you don't mind variables you simply define a new function that takes x and calls f. If you don't have a function definition there (you can generally use let or where) you can use a lambda instead.
f' x = f x 1 2 3 4
Or with a lambda
\x -> f x 1 2 3 4
Currying won't do you any good here, because the argument you want to vary (enumerate) isn't the last one. Instead, try something like this.
map (\x -> f x 1 2 3 4) [1..10]
The general solution in this situation is a lambda:
\x -> f x 1 2 3 4
however, if you're seeing yourself doing this very often, with the same argument, it would make sense to move that argument to be the last argument instead:
\x -> f 1 2 3 4 x
in which case currying applies perfectly well and you can just replace the above expression with
f 1 2 3 4
so in turn you could write:
map (f 1 2 3 4) [1..10]

Partial Application of Infix Functions in F#

In haskell it is posible to partially apply an infix function using sections, for instance given the infix function < (less than) one can partially apply any of the function's arguments: (5 <) , (< 5)
In other words, in haskell we have the following shorthand notation:
op :: a -> b -> c
(`op` y) === \x -> x `op` y
(x `op`) === \y -> x `op` y
Does F# have a similar concept?
No, neither of those (apart from standard partial application like (=) x).
Whereas I like the succinctness of Seq.find ((=) x), things like Seq.filter ((<) 3) (or even Seq.map (flip (-) 1)) are simply awkward to read and should immediately be replaced by a lambda expression, imo.
If you want to invent your own standards...
let lsection x f y -> f x y
let rsection f y x -> f x y
Then lsection 5 (<) === (5 <) and rsection (<) 5 === (< 5).
Though really, without language support, just put a lambda in there and it'll be clearer.

Resources