danke pisztoly
danke pisztoly

Reputation: 29

Function that applies a function x times on an argument

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

Answers (2)

jpmarinier
jpmarinier

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

Micha Wiedenmann
Micha Wiedenmann

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

Related Questions