Reputation: 29
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
.
Upvotes: 2
Views: 104
Reputation: 4733
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))
Upvotes: 5
Reputation: 20843
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
Upvotes: 2