I am learning Haskell. I got to know that any function in Haskell can take only one argument. So, if you see a function max 2 4; it actually is (max 2) 4. What they say is that 1st 2 is applied (as a parameter) to max which returns a functions, that takes 4 as the parameter. What I fail to understand is what happens when 2 is applied to max? What does it mean that it returns a function called (max 2)?
Let me give another example, to make my question more clear. Take this function: multiply x y x = x*y*z. They say it actually is evaluated this way: ((multiply x) y) z. Now I give this input: multiply 2*4*5
How is this evaluated?
multiply 2
returns (multiply 2) and 4 is applied as parameter:
(multiply 2) 4
Now what does this return -- ((multiply 2) 4) or multiply 8? If it multiplies 4 and 2 at this step, how does Haskell know that it has to do that (because the function can multiply only 3 parameters)?
Just think it mathematically: suppose there is a function taking two variables: f(x, y). Fix x=2 would give you a new function with one variable: g(y)=f(2, y)
If f(x, y) = max(x, y) which gives the maximum of x and y, g(y) = f(2, y) = max(2, y) gives the maximum of 2 and y.
For f(x, y, z) = x * y * z, g(y, z) = f(2, y, z) = 2 * y * z, and h(z) = g(4, z) = f(2, 4, z) = 2 * 4 * z.
Also you can fix x=2 and z=4 to form p(y) = f(2, y, 4). In Haskell it is
\y -> multiply 2 y 4
For the implementation, Haskell would not actually multiply 2 and 4 because it's lazy evaluated. That is, it would not compute a value until it has to.
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 am trying to practice some recursive functions in haskell. The following random functions show some different forms of recursions and iterations. I have problems understanding which form of recursion or iteration is connected to a function. I know the recursion forms tail recursion, linear recursion and tree recursion and the regular iteration. Is there any strategy to assign one of the four different forms i know every function?
f1 x y z = if x > y then f1 (x+2) (y-1) z else y
f2 x y z = if z /= 0 then y + x + f2 (x-1) (y-1) (z-2) else 1
f3 x y z = if y < 0 then True
else (f3 (f3 (x-2) (y-4) (z-6)) (4*y) (z-2)) + (f3 6 (y-2) (z*2))
f4 x y z = if z > 0 then (f4 (x-y) (y+1) (x-z)) + (f4 2 x z) else y+x-
(2*z)
The strategy is to look at how the return value of each recursive call is used:
In f1, the return value is itself returned immediately
In f2, the return value of a single recursive call is used to compute the return value of the original call.
In f3 and f4, the return values of multiple recursive calls are used to compute the return value of the original call.
(The fact that you need to make a recursive call to f3 in order to compute an argument for another recursive call doesn't, I think, affect any classification you are asked to make.)
I'm trying to write Karatsuba Algorithm using the divide and conquer approach in Haskell. I did it with merge sort algorithm but can't figure it out here and it's a little bit embarrassing at this point.
My main function looks like this:
dz test end divide combine x =
if test x then end x
else combine(map(dz test end divide combine) (divide x))
I test it for values 1234 and 5678: dz test end divide combine [1234, 5678,2].
So I have to write test, end, divide and combine functions.
lengthNumb x = length . show $ x
test (x:x1:xs) = (lengthNumb x) < 4 || (lengthNumb x1) < 4
end (x:y:z:xs) = [x * y, z]
This is pretty straightforward. I just check if both numbers that I want to multiply are at least 4 digits long. If not I just use simple multiplication and carry m value. I know that Karatsuba works better for bigger numbers but this is just for testing purposes.
divide [] = []
divide (x:x1:x2:xs) =
let y1 = x `div` 10^x2
y2 = x `mod` 10^x2
y3 = x2 `div` 2
z1 = x1 `div` 10^x2
z2 = x1 `mod` 10^x2
in [[y1,y2,y3],[z1,z2,y3],[y1+y2, z1+z2, y3]]
combine [[x, x1],[y,y1],[z,z1]] = x * 10^(2*x1) + y + (z - x - y) * 10^x1
I was told that combine function should only do the final multiplication. So I guess it should get three numbers as an input (each with their m value) and then also do the necessary subtraction ( z-x-y ) because I couldn't do it in divide.
But this is wrong. I get an error:
Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [[a]] -> [a]
Actual type: [[[a]]] -> [a]
I think it is a problem with the parameters of combine function but I don't know how to fix it. I also think that there could be a problem with how combine and divide work together because in one of the previous iterations the final result of multiplication was wrong.
I am having a hard time trying to figure out how does this function works, and I need an explanation from an expert. Appreciate any help!
puzzle n x = scanr (\y acc -> (acc + y/acc)/2) 1 (replicate n x)
I tried running these:
--puzzle 10 2
--puzzle 10 5
--puzzle 10 36
and it gives me this output, respectively:
[1.414213562373095,1.414213562373095,1.414213562373095,1.414213562373095,1.414213562373095,1.414213562373095,1.4142135623746899,1.4142156862745097,1.4166666666666665,1.5,1.0]
[2.23606797749979,2.23606797749979,2.23606797749979,2.23606797749979,2.23606797749979,2.236067977499978,2.2360688956433634,2.238095238095238,2.3333333333333335,3.0,1.0]
[6.0,6.0,6.0,6.0,6.000000005333189,6.0002529841194185,6.055351744849479,6.872226737643129,10.222972972972974,18.5,1.0]
This function calculates a square root using Newton`s formula and stores all iteration results in list.
Here is a Newton's method on wiki.
Storing process is based on definition of scanr function:
scanr is similar to foldr, but returns a list
of successive reduced values from the right
It makes a list of n x-es like [x,x,x,x,x,..] (n times)
and then what it does is:
x1 = ( 1 + x/1)/2
x2 = (x1 + x/x1)/2
x3 = (x2 + x/x2)/2
x4 = (x3 + x/x3)/2
and the result is [xn,x(n-1),...,x2,x1]
I started learning Haskell recently and in my class right now, we have constructed a Peano number class and instanced it in the Num typeclass.
During lecture, my professor claimed that depending on whether you viewed the successor function as S x = x + 1 or S x = 1 + x, the appropriate successor case for the multiplication definition would be different. Respectively:
x * S y = x * y + x
x * S y = x + x * y
Moreover, he claimed that using the first of these two choices is preferable because it is lazier but I'm having trouble seeing how this is the case.
We looked at the example in which the addition definition of
x + S y = S (x + y)
is better than
x + S y = S x + y
because evaluating x + y == z occurs much faster but I can't find an analogous case for multiplication.
The lecture notes are here: http://cmsc-16100.cs.uchicago.edu/2014/Lectures/lecture-02.php
Laziness is not about speed but what is available how soon.
With x * S y = x * y + x then you can answer infinity * 2 > 5 very quickly, because it will expand as so:
infinity * (S (S Z)) > 5
infinity * (S Z) + infinity > 5
infinity * Z + infinity + infinity > 5
infinity + infinity > 5
(from there the rest is trivial)
However, I don't think it is all as good as your professor claimed! Try to expand out 2 * infinity > 5 in this formalism and you'll be disappointed (or busy for a very long time :-P). On the other hand, with the other definition of multiplication, you do get an answer there.
Now, if we have the "good" definition of addition, I think it should be the case that you can get an answer with infinities in either position. And indeed, I checked the source of a few Haskell packages that define Nats, and indeed they prefer x * S y = x + x * y rather than the way your professor claimed was better.