10

How would I make this Haskell power function tail recursive?

turboPower a 0 = 1
turboPower a b
    | even b = turboPower (a*a) (b `div` 2)
    | otherwise = a * turboPower a (b-1)
NoviceCodingGeek
  • 226
  • 4
  • 17
Linda Cohen
  • 217
  • 2
  • 9

1 Answers1

10
turboPower a b = turboPower' 1 a b
  where
    turboPower' x a 0 = x
    turboPower' x a b
        | x `seq` a `seq` b `seq` False = undefined
        | even b = turboPower' x (a*a) (b `div` 2)
        | otherwise = turboPower' (x*a) a (b-1)

Basically, what you want to do is move the multiplication that you're doing in the "otherwise" step (since that's what keeps this from being tail-recursive initially) to another parameter.

Edited to add a line making all three parameters strictly evaluated, instead of lazy, since this is one of those well-known situations where laziness can hurt us.

Daniel Martin
  • 23,083
  • 6
  • 50
  • 70
  • It looks like you'll want to make the tail recursive version strict in the accumulator argument. Otherwise, your turboPower will probably cause memory exhaustion when the result of the computation is demanded. – Jason Dagit May 07 '10 at 21:58
  • Good point - and I also want to make it strict in `a` too. Done. – Daniel Martin May 08 '10 at 18:51