Int - >整数:输入对话误解

时间:2012-02-24 05:25:11

标签: haskell

这是我计算斐波纳契数的代码:

f' :: (Int -> Int) -> Int -> Int
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)

f'_list :: [Int]
f'_list = map (f' faster_f') [0..]

faster_f' :: Int -> Int
faster_f' n = f'_list !! n

它很好,而'n'很小。要解决大数字的问题,我想将Int-type转换为Integer:

f' :: (Integer -> Integer) -> Integer -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)

f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]

faster_f' :: Integer -> Integer
faster_f' n = f'_list !! n

使用此代码我收到错误:

Couldn't match expected type `Int' with actual type `Integer'
In the second argument of `(!!)', namely `n'
In the expression: f'_list !! n
In an equation for `faster_f'': faster_f' n = f'_list !! n

好吧,我已经正确理解了列表中元素的索引不能是Integer-type。 OK:

f' :: (Integer -> Integer) -> Integer -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)

f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]

faster_f' :: **Int** -> Integer
faster_f' n = f'_list !! n

但现在我收到了错误:

  

无法匹配预期类型Integer' with actual type Int'       预期类型:整数 - >整数

  Actual type: Int -> Integer
In the first argument of `f'', namely `faster_f''
In the first argument of `map', namely `(f' faster_f')'

为什么呢?我该如何解决?

3 个答案:

答案 0 :(得分:8)

最简单的方法是创建参数Int(因为它们是Fibonacci数的索引,而不是数字的索引),并仅使用Integer作为输出:

f' :: (Int -> Integer) -> Int -> Integer
f' mf 0 = 0
f' mf 1 = 1
f' mf n = mf(n - 2) + mf(n - 1)

f'_list :: [Integer]
f'_list = map (f' faster_f') [0..]

faster_f' :: Int -> Integer
faster_f' n = f'_list !! n

当然,现在你无法解决索引超出Int范围的斐波那契数字,但实际上你的空间和时间都会用尽,更多,更快。

顺便说一下,如果你需要一个fib列表,那么“通常”的实现就是

fibs :: [Integer]
fibs = 0 : scanl (+) 1 fibs

如果您只需要某些值,则使用这些公式有一种类似于快速求幂的快速计算方法:

f(2n) = (2*f(n-1) + f(n)) * f(n) 
f(2n-1) = f(n)² + f(n-1)²

答案 1 :(得分:7)

  

为什么?

由于f'需要Integer -> Integer功能,但您发送的是faster_f',这是Int -> Integer功能。

  

我该如何解决?

最简单的方法可能是使用genericIndex(来自Data.List)而不是(!!)

答案 2 :(得分:2)

Integer是无限类型的Int,(Int仅保证覆盖从-2^292^29-1的范围,但在大多数实现中,它是完整的32或64位类型)。这就是你得到第一个错误的原因。您得到的第二个错误是因为(!!)是一个采用列表和Int

的函数
(!!) :: [a] -> Int -> a

还有很多其他(也许更容易)的方法来计算斐波纳契数。这是一个示例,它返回指定的所有Fibonacci数列表。第一个电话是由fibCall

完成的
fib :: Integer -> Integer -> Integer -> [Integer] -> [Integer]
fib 0 _ _ l  = l
fib n a b l  = fib (n-1) b (a+b) (a:l)

fibCall :: Integer -> [Integer]
fibCall n = n 1 1 []

如果您只想要n th 斐波纳契数,请将[Integer]更改为Integer,将(a:l)更改为a