views:

212

answers:

1
turboPower a 0 = 1
turboPower a b
    | even b = turboPower (a*a) (b `div` 2)
    | otherwise = a * turboPower a (b-1)

THANKS!

+8  A: 
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
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
Good point - and I also want to make it strict in `a` too. Done.
Daniel Martin