Write a doItX :: (a -> a -> a) -> a -> Int -> a
function that applies the first parameter f
x
times on the second parameter.
doItX (*) 2 1 == 2
doItX ( ) "a" 6 == "aaaaaa"
doItX (*) 2 3 == 8
I have the following code:
doItX f a x
| x==1 = a
| x>1 = doItX f (f a a) (x-1)
That works fine if x
is 2 or less, but for the third example, it returns 16
instead of 8
.
CodePudding user response:
Probably the most “idiomatic” solution would be a library-based one:
doItX1 :: (a -> a -> a) -> a -> Int -> a
doItX1 f a x = foldr1 f (replicate x a)
with Prelude function foldr1 documented here.
But if for some reason of yours, you insist on using manual recursion, your code was almost there. You just need to fix the recursive call:
doItX :: (a -> a -> a) -> a -> Int -> a
doItX f a x
| (x > 1) = ----Was: doItX f (f a a) (x-1)
f a (doItX f a (x-1))
| (x == 1) = a
| otherwise = error ("doItX called with x set to " (show x))
CodePudding user response:
Let's consider doItX (*) 2 3
.
doItX (*) 2 3
-- doItX f a x
-- f = (*)
-- a = 2
-- x = 3
-- doItX f (f a a) (x-1)
doItX (*) ((*) 2 2) 2
doItX (*) 4 2
doItX (*) ((*) 4 4) 1 -- ups, you wanted `2 * 4` but got `4 * 4`.
-- You probably should always pass 2 for a.
16