1

这是一个 Haskell 函数,它接受一个数字n并返回第 n 个斐波那契数。(我使用的索引方案是第 0 个数字是 0,第一个数字是 1,第 2 个数字是 1,第 3 个数字是 2,依此类推。)

fib :: (Integral a) => a -> a
fib 0 = 0
fib n = fibhelper n 0 1

fibhelper :: (Integral a) => a -> a -> a -> a
fibhelper 1 x y = y
fibhelper n x y = fibhelper (n-1) y (x+y)

现在,假设为了提高效率,我想绕过 Haskell 的惰性求值并强制对更新的参数进行求值($!例如,使用运算符?)最优雅/惯用的方法是什么?

4

1 回答 1

8

您可以使用 bang 模式来执行此操作。

{-# LANGUAGE BangPatterns #-}

fib :: (Integral a) => a -> a
fib 0 = 0
fib n = fibhelper n 0 1

-- Everything with a ! before it will be evaluated before the function body
fibhelper :: (Integral a) => a -> a -> a -> a
fibhelper 1 _ (!y) = y
fibhelper (!n) (!x) (!y) = fibhelper (n-1) y (x+y)
-- The above line is equivalent to:
--fibhelper n x y = n `seq` x `seq` y `seq` fibhelper (n-1) y (x+y)

另请注意,您对Integral类型类的使用有点过分热心。您真的希望斐波那契数列的索引与值的类型相同吗?我建议您改用签名:

fib :: (Integral a, Integral b) => a -> b

此外,如果您正在寻找性能,Integral则应完全避免使用。

于 2012-08-19T16:05:38.640 回答