通常,对于尾递归函数,您需要一个累加器参数 - 如果具有纯度,则结果可能仅取决于达到的基本情况。因此,您需要一个辅助函数,该函数还带有一个累加器参数,并使用累加器的初始值调用它,
hexToInteger :: String -> Integer
hexToInteger string = hexToIntegerHelper initialAccumulator string
你必须找出
- 你应该为累加器传递什么初始值
- 如何在每个步骤中更新累加器。
例如,尾递归实现reverse
是
reverse :: [a] -> [a]
reverse xs = reverseHelper [] xs
reverseHelper :: [a] -> [a] -> [a]
reverseHelper accumulator [] = accumulator
reverseHelper accumulator (x:xs) = reverseHelper (x:accumulator) xs
和一个尾递归阶乘(捏造否定论点的情况)
factorial :: Integer -> Integer
factorial n = factorialHelper 1 n
factorialHelper :: Integer -> Integer -> Integer
factorialHelper accumulator n
| n < 2 = accumulator
| otherwise = factorialHelper (n*accumulator) (n-1)
所以你可以看到 的一般结构hexToIntegerHelper
,
hexToIntegerHelper :: Integer -> String -> Integer
hexToIntegerHelper accumulator "" = accumulator
hexToIntegerHelper accumulator (d:ds) = hexToIntegerHelper (newAccumulatorFrom accumulator d) ds
问题是如何从旧的累加器和十六进制数字计算新的累加器(以及初始累加器应该是什么)。
对于累加器的更新,
digitToInt :: Char -> Int
fromData.Char
可能很有用,它可以处理所有十六进制数字。但是,它不会返回所需的类型,因此您需要使用 afromIntegral
或 atoInteger
将其转换Int
为Integer
.