Как я могу сделать эту функцию мощности Haskell рекурсивной?Как вы делаете эту функцию мощности Haskell рекурсивной?
turboPower a 0 = 1
turboPower a b
| even b = turboPower (a*a) (b `div` 2)
| otherwise = a * turboPower a (b-1)
Как я могу сделать эту функцию мощности Haskell рекурсивной?Как вы делаете эту функцию мощности Haskell рекурсивной?
turboPower a 0 = 1
turboPower a b
| even b = turboPower (a*a) (b `div` 2)
| otherwise = a * turboPower a (b-1)
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)
В принципе, то, что вы хотите сделать, это переместить умножение, что вы делаете в «otherwise
» шаг (так как это то, что держит это от того, хвостовой рекурсией изначально) к другому параметру.
Отредактировано для добавления строки, в которой все три параметра строго оцениваются, а не ленивы, так как это одна из тех известных ситуаций, когда лень может нанести нам вред.
Похоже, вы захотите сделать хвостовую рекурсивную версию строгой в аргументе аккумулятора. В противном случае ваш turboPower, вероятно, приведет к исчерпанию памяти, когда потребуется результат вычисления. –
Хорошая точка - и я также хочу сделать ее строгой в 'a' тоже. Готово. –
Вам не нужно '>' перед кодом. Просто отступьте его четырьмя пробелами. –
Кстати, вы, вероятно, должны использовать 'quot' вместо' div'. Также обратите внимание, что обычный '(^)' также основан на алгоритме быстрого возведения в степень. – dfeuer