I am trying to write this function which applies the function f twice on x
Prelude> applyTwice :: (a -> a) -> a -> a
Prelude> let applyTwice f x = f (f x)
Now, when I try to evaluate the below expression
Prelude> applyTwice (`subtract` 3) 10
Output: 10
Prelude> applyTwice (3 `subtract`) 10
Output: 4
As per my understanding, subtract is a infix function, so the given parameter should fill the empty position (left or right operand) and hence the first expression applyTwice (`subtract` 3) 10 should behave like
10 `subtract` 3 `subtract` 3
So, the result in this case should be 4, but the output is 10
While in the other case, i.e. applyTwice (3 `subtract`) 10, the output is 4, where I am expecting it to be 10
Am I going wrong somewhere?
Your understanding of applyTwice and of the operator section notation are correct. However, you're probably confused by what subtract does. See the library documentation which says:
the same as flip (-)
So subtract is like (-) but with the arguments flipped. Therefore,
applyTwice (`subtract` 3) 10
=
(`subtract` 3) ((`subtract` 3) 10)
=
(`subtract` 3) (10 `subtract` 3)
=
((10 `subtract` 3) `subtract` 3)
=
(3 - 10) `subtract` 3
=
(-7) `subtract` 3
=
3 - (-7)
=
10
And similarly for the other expression.
Related
Recently I have been learning about compositions in haskell and am now a bit confused concerning this example.
(const . min) 3 0 4
As a result I get 3, so internally it must be computed like:
const (min 3) 0 4
But I thought since min takes two arguments, it should look like this:
const (min 3 0) 4
So apparently the composition only takes this one argument, in this case 3, instead of all the arguments for min like I expected it to. Does that mean compositions only take one argument per default or what am I not getting here?
You can answer your question by manually evaluating the initial expression.
(const . min) 3 0 4
⇒ (\x -> const (min x)) 3 0 4 * defn of (.)
⇒ (const (min 3)) 0 4 * function application
⇒ ((\x y -> x) (min 3)) 0 4 * defn of const
⇒ (\y -> min 3) 0 4 * function application
⇒ (min 3) 4 * function application
⇒ 3 * because 3 is less than 4
It is worth noting that function application is left-associative, so, f x y means the same as (f x) y.
It is also worth noting that \x y -> z means the same as \x -> \y -> z.
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.
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.
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
I'm trying to write a hyperoperation function in haskell.
It's usually wrritten as ackermann(a,b,n) but for partial application purposes I think it makes more sense to put n first. As such I'm calling it hypOp n a b
The form I've found most natural uses folds ao replicate lists like this:
Prelude> replicate 3 5
[5,5,5]
Prelude> foldr1 (*) $ replicate 3 5
125
Depending on the function argument to the fold this can be addition, mutliplication, exponentiation, tetration, etc.
Informal Overview:
hypOp 0 a _ = succ a
hypOp 1 a b = a + b = foldr1 (succ a) (replicate b a) --OFF BY ONE ISSUES, TYPE ISSUES
hypOp 2 a b = a * b = foldr1 (+) $ replicate b a
hypOp 3 a b = a ^ b = foldr1 (*) $ replicate b a
hypOp 4 a b = = foldr1 (^)
For associative reasons I am under the impression I must use right folds, which is unfortunate because the strictness available with left folds (foldl') would be useful.
Right vs. left folds issue
Prelude> foldl1 (^) $ replicate 4 2 --((2^2)^2)^2 = (4^2)^2 = 16^2 = 256 != 2 tetra 4
256
Prelude> foldr1 (^) $ replicate 4 2 --(2^(2^(2^2))) = 2^16 = 65536 == 2 tetra 4
65536
I get an off-by-one issue when i 'start' a the very beginning with successor function. so instead im using (+) as the function for my base fold
Prelude> let add a b = foldr1 (\a b -> succ b) $ replicate b a
Prelude> add 5 4
8
Prelude> add 10 5 --always comes out short by one, so i cant build off this
14
First few n values, done 'manually':
Prelude> let mul a b = foldr1 (+) $ replicate b a
Prelude> let exp a b = foldr1 mul $ replicate b a
Prelude> let tetra a b = foldr1 exp $ replicate b a
Prelude> let pent a b = foldr1 tetra $ replicate b a
Prelude> let sixate a b = foldr1 pent $ replicate b a
Prelude> mul 2 3 --2+2+2
6
Prelude> exp 2 3 --2*2*2
8
Prelude> tetra 2 3 --2^(2^2)
16
Prelude> pent 2 3 --2 tetra (2 tetra 2)
65536
Prelude> sixate 2 3
*** Exception: stack overflow
My attempt at formal definitions thru above approach:
hypOp :: Int -> Int -> Int -> Int
hypOp 0 a b = succ a
hypOp 1 a b = (+) a b --necessary only bc off-by-one error described above
hypOp n a b = foldr1 (hypOp $ n-1) (replicate b a)
Other attemp twith recursive array (not different in any significant way):
let arr = array (0,5) ( (0, (+)) : [(i, (\a b -> foldr1 (arr!(i-1)) (replicate b a)) ) | i <- [1..5]])
-- (arr!0) a b makes a + b
-- (arr!1) a b makes a * b, etc.
So my questions are...
Any general suggestions, different appraoches to t he function? I cant seem to find a way to avoid overflows except for using a very 'imperative' style which is not my intention when using haskell and trying to code in an idiomatic style
How my off-by-one issue can be dealt with so I can start 'properly' at the very bottom with succ
Strictness and left vs. right folds. Is there a way to work in seq? Some way that I can use foldl1' instead of foldr1 and avoid the problem described above?
See point 3. Although it works to define these operations in this way, and you can do it without overflows, it is an extremely inefficient approach. Your run time is linear in the answer, because you end up doing repeated addition.
The reason why you're getting the off-by-one is basically because you're using foldr1 f instead of foldr f with an identity.
foldr (+) 0 [a, a, a] = a + (a + (a + 0)))
foldr1 (+) [a, a, a] = a + (a + a)
Notice there is one less application of + in the case of foldr1.
How about simply changing the order of arguments to (^)? That way, you can use a left fold:
Prelude Data.List> foldl1 (flip (^)) $ replicate 4 2
65536
Now you can use the strict version, foldl1'. It no longer overflows, but it is of course extremely inefficient.