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.)
Related
Suppose I want to build a list iterate step x0 in Haskell, but with an inclusive termination condition. So in Python this would be list(my_gen) where e.g.
def my_gen():
x = x0
while not done(x):
x = step(x)
yield x
(Edit: This should have an additional yield x before the loop if I want to include x0.)
One way would be to write my own takeWhileInclusive and say
takeWhileInclusive (not . done) . iterate step x0
Is this the Haskell-y way (or a Haskell-y way) to accomplish this? It seems unnatural to try to tack on some sentinel value for step x when done x is true and then use takeWhile.
In particular I'm thinking of the container with most water problem on LeetCode, and solving it with something like
maxWith volume . smartSteps (0, n)
where smartSteps = takeWhileInclusive (\(i,j) -> j - i > 1) . iterate step
and step increases i or decreases j (or both), according to which index has the higher line.
Of course here it would be easy to just use takeWhile j > i, but I wanted to think how I would approach situations where there isn't a natural "you went too far" condition, just a "you are done" condition.
Edit: This question has been marked as a duplicate (of a question which I had linked to in my question), but it is not. The question is not how to write takeWhileInclusive, in fact the question explicitly takes takeWhileInclusive as given. It is about how to accomplish a task that may or may not use takeWhileInclusive.
You can use unfoldr to generate the sequence:
unfoldr (\x -> if done x then Nothing else Just (x, step x)) x0
For example,
> import Data.List
> step = (+1)
> done = (> 10)
> x0 = 0
> unfoldr (\x -> if done x then Nothing else Just (x, step x)) x0
[0,1,2,3,4,5,6,7,8,9,10]
unfoldr calls its function on x0 to start. When the function returns Nothing, unfoldr stops. When the function returns Just (x, y), it appends x to the result and calls the function again on y.
Compare your generator to a Python implementation of unfoldr:
def unfoldr(f, x):
while True:
if (y := f(x)) is None:
return
else:
yield y[0]
x = y[1]
list(unfoldr(lambda x: None if done(x) else (x, step(x)), x0))
Yes, that is a Haskell-y way.
Another Haskell-y way (or a Haskell-y way to implement takeWhileInclusive) is to zip up the iterated values with one step later.
myGen done step = map snd . takeWhile (not . done . fst) . ap zip tail . iterate step
N.B. unlike iterate (but like my_gen) this does not emit the initial x value as one of the steps.
You can define
takeUntil done xs =
foldr (\x r -> if done x then [x] else x : r) [] xs
and then use it like
takeUntil done $ iterate step x0
e.g. takeUntil (> 9) [1..] == [1..10].
It's easy to specify the final element with foldr (as is seen here), but more cumbersome to do that with unfoldr which encodes an "anamorphism", closing the generated list with an empty list as the sentinel. Specifying the non-empty tail is possible with an "apomorphism", which seems like it would be the fitting tool for this task.
I am new to Haskell.
In Yet Another Haskell Tutorial, page Type Basics, I find this example:
count2 bTest list = foldr (\x cnt -> if bTest x then cnt+1 else cnt) 0 list
but I think that the lambda function
\x cnt -> if bTest x then cnt+1 else cnt
is not a pure function, given that its behavior depends on something external to the function, namely the function bTest. Is this correct?
Lambda abstractions are expressions which denote function values, much like arithmetic expressions denote numeric values. Both kinds of expressions might refer to variables defined elsewhere, and this does not break "purity"/referential transparency.
The value of the arithmetic expression
2*x + 1
depends on the value of x, but that does not make the above code "impure". Consider the function
f :: Int -> Int
f x = 2*x + 1
This produces the same output value for the same input value, so it it pure.
Now, consider the lambda expression
\y -> 2*x + y
This denotes a function value which depends on x, much like the arithmetic expression depends on x. There's no difference in this regard.
Indeed, the function
g :: Int -> (Int -> Int)
g x = \y -> 2*x + y
is pure: given the same x, it returns the same output value, which is a function. And, on top of that, the returned function is pure: given the same y, it returns the same numeric value. To stress the point
let h = g 5
in h 23 == h 23
evaluates to True since both h 23 evaluate to 2*5+23.
By comparison, this evaluates to False
let h1 = g 5
h2 = g 1
in h1 23 == h2 23
since we compare 2*5+23 against 2*1+23. This, however, does not break purity since h1 and h2 are different function values: we are not calling the same function with the same input, and that can indeed produce different results.
No this is not correct.
The lambda function returns the same output for the same input any time it is called, without any other effects.
To do that it does depend on the value of a parameter to the outer function, but that's just a detail.
In different invocations of count2 there might be used different values for bTest. In such situations the two lambda function will be different, yes, but the bTest values serve as a hidden implicit input. Still, the same inputs entailing the same output, which is the definition of "pure".
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 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.
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]