【问题标题】:Int -> Integer: type conversation misunderstandingInt -> Integer:类型对话误解
【发布时间】:2012-02-24 18:29:36
【问题描述】:

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

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

好吧,我已经正确理解了列表中元素的索引不能是整数类型。 好的:

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 typeInt' 预期类型:整数 -> 整数

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

为什么?我该如何解决?

【问题讨论】:

  • Int 切换到Integer 不会不会让您的代码更快;事实上,我希望它会变慢......
  • 问题不在于速度,而在于类型溢出。 fast_f' 100 - 与 Int 类型一起工作不正确
  • 对不起,我的错误;我误读了您写的内容:s

标签: haskell


【解决方案1】:

最简单的方法是将参数设为Int(因为它们是斐波那契数字的索引,而不是数字本身),并使用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)²

【讨论】:

    【解决方案2】:

    为什么?

    因为f' 需要一个Integer -> Integer 函数,但您发送它的是faster_f',它是一个Int -> Integer 函数。

    我该如何解决?

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

    【讨论】:

      【解决方案3】:

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

      (!!) :: [a] -> Int -> a
      

      还有很多其他(也许更简单)的方法来计算斐波那契数。这是一个将所有斐波那契数列返回到指定值的示例。第一通电话是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 []
      

      如果您只想要第 nth 个斐波那契数,请将 [Integer] 更改为 Integer 并将 (a:l) 更改为 a

      【讨论】:

        猜你喜欢
        • 2011-12-19
        • 2011-09-22
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多