Why it's possible to reduce function in Haskell:
calculate :: Integer -> Integer -> Integer
calculate a b = f 1 a b
where
f :: Integer -> Integer -> Integer -> Integer
f a b c = a + b
into something:
calculate :: Integer -> Integer -> Integer
calculate = f 1
where
f :: Integer -> Integer -> Integer -> Integer
f a b c = a + b
I just need some guidance, any resources where I can find the answer and read more about it would be really helpful.
In Haskell there are no functions that take more than one parameter. All functions take exactly one parameter.
So if you have a function like add :: Int -> Int -> Int, then this is actually short for add :: Int -> (Int -> Int).
Why are the brackets important? Because they show how this concept works. If we have this function add, then we can make a function application with for example 14, then we construct a new function, like:
add14 :: Int -> Int
add14 = add 14
so that means that we now have a function that takes again one parameter (here an Int), and now it will produce another Int, it does that by adding 14 to it, so add14 25 will result in 39.
If you write add 14 25, this thus is not a function application with two parameters, what you actually wrote is:
-- add 14 25 is equivalent to
(add 14) 25
You thus first make a call with 14, and the you make a call with the function that comes out of this, and 25 as the parameter.
Why is this important? Because it means that if you thus write
calculate = f 1
it means that your f 1, constructs a function, a function with signature Int -> (Int -> Int). Creating parameters in the head of calculate, and adding these to the end of f 1, thus makes no sense: you already constructed a function that takes such parameters anyway. So it only introduces noise.
In lambda calculus, the rewrite rule where one rewrites λ x . f x to just f is (and vice versa) is called η-conversion [wiki]. In Haskell it comes down to rewriting:
f x = g x
to:
f = g
Operators are no different. In fact if you write a + b in Haskell, you wrote (+) a b, with (+) a function, or more verbose ((+) a) b.
The f in the where clause:
f a b c = a + b
can for example get converted to:
f = (.) ((.) const) (+)
It's called eta reduction.
You might also think about it in terms of partial application.
> calculate :: Integer -> Integer -> Integer
> f :: Integer -> Integer -> Integer -> Integer
> (f 1) :: Integer -> Integer -> Integer
Similar question - What does eta reduce mean in the context of HLint
Related
I'm still learning Haskell and I'm really confused with this language... i have to implement two functions fromInteger :: Integer -> String and toInteger :: String -> Integer that translate between Haskell integers and numbers by strings of digits in reverse order, like: "25" -> "52". For the sake of functional decomposition i should first implement fromDigit :: Integer -> Char and toDigit :: Char -> Integer
that translate between digits and characters.
How should the function look like?
Thanks a lot!
You can use read :: Read a => String -> a and show :: Show a => a -> String to convert from Integer and to a String:
Prelude> show 52
"52"
Prelude> read "52" :: Integer
52
But you do not need to convert values to a string to reverse the order of the digits. You can use recursion and quotRem :: Integral a => a -> a -> (a, a) to obtain the quotient and remainder.
You can also use recursing to convert an Integer to a String. Here we use as accumulator a String, and we each time calculate the last digit. This thus looks like:
fromInteger :: Integer -> String
fromInteger = go []
where go ls x | x <= 9 = … : …
| otherwise = go (… : ls) …
where (q, r) = quotRem x 10
where you still need to fill in the … parts.
I have a hard time to understand Currying in Haskell. I was not able to understand the already existing answers to this topic. I want to understand what the difference is between:
(Int -> Int) -> Int
and
Int -> (Int - > Int)
I think the answer has something to do with currying. I have already consulted some resources about the topic and I have got an idea.
Functions that have several parameters can be described as an array of elementary operations with one input and one output.
According to the online tutorial learnyouahaskell:
"Doing max 4 5 first creates a function that takes a parameter and returns either 4 or that parameter, depending on which is bigger. Then, 5 is applied to that function and that function produces our desired result."
So in this case the elementary basic operations are just comparing two values. And the first operation is
if "lowest value possible" > 4 then "lowest value possible" otherwise 4
The second operation is
if 4 > 5 then 4 otherwise 5
This would represent Int -> (Int -> Int) but what would (Int -> Int) -> Int be?
Int -> (Int -> Int)
is the same type as
Int -> Int -> Int
and is the type of a curried two-arguments function, both being integers. That is it is a function which takes an integer argument and returns a function, whose argument is another integer, and which finally returns an integer.
Possible calls are f 3 2 and f (7+4) (5*8).
Possible definitions are f a b = a+b and f a b = a*a+42*b.
Instead,
(Int -> Int) - > Int
is not a binary function, curried or not. It is a function with a single argument, and this argument is a function Int -> Int. The final result is an integer.
Possible calls are f (\x -> x+1), f id, and f g where g n = n*4+5.
Possible definitions are f h = h 45 and f h = h (h 6) + h 7 + 9.
The idea of partial function application is a hallmark of Haskell.
Exploiting partial application is natural. It is much how we think.
I fill my glass half with tea. Then I fill it completely with lemonaid.
m2 = max 4 --partial application (Int -> Int)
m2 5 -- full application (Int -> Int) -> Int
All functions in Haskell are curried. It is sometimes necessary to disable it with uncurry
m3 = uncurry max
m4 = m3 4 -- does not become (Int -> Int)
m4 3 -- is not (Int -> Int) -> Int -> Int
Does not work and the error has to do with partial application (Int -> Int) because the function now requires two parameters.
I have the following function in Haskell:
invertedSum :: Integer -> Integer
invertedSum n = n + (read . reverse . show) n
I need to know the number of sums that must be made in order for the number to be capicua. That is to say,
invertedSum 1999 = 11990 (1999+9991)
invertedSum 11990 = 21901
invertedSum 21901 = 32813
invertedSum 32813 = 64636
invertedSum 64636 = 128282
invertedSum 128282 = 411103
invertedSum 411103 = 712217
isCapicua :: Integer -> Bool
isCapicua n | show n == (reverse . show) n = True
| otherwise = False
isCapicua 712217 == True
So, I want to generate the following list, but I don't know how.
sumUpToCapicua 1999 = [11990, 21901, 32813, 64636, 128282, 411103, 712217]
genericLength (sumUpToCapicua 1000000079994144385) == 259
You already have a function invertedSum with the type Integer -> Integer. If I understand the question correctly, you'd like to apply it multiple times, starting with a particular Integer (e.g. 1999).
You could use iterate for that purpose. It has the type:
Prelude> :t iterate
iterate :: (a -> a) -> a -> [a]
In other words, it'll take any function a -> a, as well as an initial value a, and produce an infinite list of a values.
In your case, invertedSum has the type Integer -> Integer, and the initial value you'd like to use (e.g. 1999) would also be of the type Integer, so it all fits: a would be Integer.
Try using invertedSum and e.g. 1999 with iterate. Be aware that this produces an infinite list, so if you experiment with this in GHCi, you probably want to use e.g. take 10 to cap the number of values generated.
for a homework assignment, a subtask is to make the arithmetic functions (+), (-), (*) and div showable.
We're solved the rest of the assignment, but we're stuck here. Right now we're using the solution to this question here to distinguish between the operations:
showOp op = case op 3 3 of
6 -> "plus"
0 -> "minus"
9 -> "times"
1 -> "divide"
_ -> "undefined"
However, this strikes me as kind of ugly as things like showOp (\a b -> a * 3 - y) yield "plus".
Is there any way to better distinguish between the operators?
We are using winhugs atm with the appropriate switches -98 +o in order to be able to use the needed extensions.
Edit:
As requested, the actual assignment has to do with Arrays (specifically Array Int (Int -> Int -> Int)). It has to do with generating arrays of operators that fulfill certain conditions.
The assignment states:
Make the data type Array Int (Int->Int-Int) an Instance of Show. The arithmetic operations from the previous exercises should be represented as "plus", "minus", "times" and "div".
thx for any help in advance
Use induction :)
{-# LANGUAGE FlexibleInstances #-}
instance Eq (Int-> Int -> Int) where
f == g = induce f g where
base = 1
n = 2
induce f g = and [f 1 n' == g 1 n' | n' <- [base, n, n+1]]
instance Show (Int-> Int -> Int) where
show a = showOp a where
showOp op = case lookup op ops of
Just a -> a
otherwise -> "undefined"
ops = [((+),"plus")
,((-),"minus")
,((*),"times")
,(div,"divide")]
Output:
*Main> (\a b -> a * 3 - b) :: (Int->Int->Int)
undefined
I want to know whether shift is a higher order function or not.
chartoInt :: Char -> Int
chartoInt c = ord c
Inttochar :: Int -> Char
Inttochar n = chr n
shift :: Int -> Char -> Char
shift n c = Inttochar (chartoInt c + n)
None of these functions are higher order functions, because none of these functions take a function as a parameter.
shift's parameters are n (an Int) and c (a Char): neither are functions.
(Also: Inttochar should be inttochar: function names in Haskell cannot start with an upper case letter.)
Here's a higher order function that looks like your shift:
higherShift :: (Int -> Char) -> Int -> Char -> Char
higherShift f n c = f (chartoInt c + n)
shift = higherShift inttochar -- same as your original shift
Or, perhaps more usefully:
anotherHigherShift :: (Int -> Int) -> Char -> Char
anotherHigherShift f c = inttochar (f (chartoInt c))
shift n = anotherHigherShift (+n) -- same as your original shift
You can read the type signature for anotherHigherShift as saying that
it's a function
whose first parameter is a function (this function takes an Int and returns an Int)
whose second parameter is a Char
and which returns a Char
(+n) is shorthand for \m -> m + n.
It is.
The shift is a higher order function.
shift :: Int -> (Char -> Char) -- The long prototype.
It get Int and return function getting Char and returning Char.
P.S.
You should write inttochar.
There is informal rule: take a look at function's type. If it contains (with necessity [1]) braces, than it's a higher order function.
[1] In the meaning that omitting them changes the type.
And now take a look at types of your function and functions from first answer from this point of view. It's simple.