【问题标题】:Couldn't match expected type ‘[Integer]’ with actual type ‘Integer’无法将预期类型“[Integer]”与实际类型“Integer”匹配
【发布时间】:2017-03-12 01:15:25
【问题描述】:

我正在创建一个斐波那契数列中小于或等于 4,000,000 的所有偶数的列表。在 Haskell 中,我将斐波那契数列定义为:

fibs = 1 : 2 : next fibs
  where
    next (a : t@(b:_)) = (a+b) : next t

并且我正在使用以下列表推导来构建我的集合:

[ x | x <- take 50 fibs, x `mod` 2 == 0, last x <= 4*10^6 ]

但是,GHC 抛出 Couldn't match expected type ‘[Integer]’ with actual type ‘Integer’ 错误。

我了解谓词last x &lt;= 4*10^6 是造成错误的原因。受 hammar 的回答 here 的启发,我最初的反应是确保 4*10^6 是正确的类型,所以我尝试将谓词改写为 last x &lt;= toInteger 4*10^6 无济于事;同样的错误。我还认为也许我需要将4*10^6 指定为单例(即[4*10^6]),但也没有运气。

我很难理解到底发生了什么以及如何最好地解决问题。

【问题讨论】:

    标签: haskell


    【解决方案1】:
    sum [ x | x <- take 50 fibs, x `mod` 2 == 0, last x <= 4*10^6 ]
    

    take 50 fibsInteger ([Integer]) 的列表,x 是该列表的一个元素(因此是Integer)。 last 是一个接受列表的函数...

    GHCi> :t last
    last :: [a] -> a
    

    ...但是您将Integer 传递给它。您不需要last 来过滤列表理解中的元素;只需使用:

    sum [ x | x <- take 50 fibs, x `mod` 2 == 0, x <= 4*10^6 ]
    

    顺便说一句,鉴于您知道fibs 中的数字总是增加,您可以将表达式写为:

    -- (<= 4*10^6) is shorthand for (\x -> x <= 4*10^6)
    sum [ x | x <- takeWhile (<= 4*10^6) fibs, x `mod` 2 == 0 ]
    -- Three equivalent alternatives:
    (sum . takeWhile (<= 4*10^6)) [ x | x <-  fibs, x `mod` 2 == 0 ]
    (sum . takeWhile (<= 4*10^6) . filter (\x -> x `mod` 2 == 0)) fibs
    (sum . takeWhile (<= 4*10^6) . filter ((== 0) . (`mod` 2))) fibs
    

    这样您就不需要 50 个元素的任意限制。

    【讨论】:

    • 太棒了。我的问题是将x 视为一个列表。欣赏周到的解释和额外的选择。
    【解决方案2】:
    fibs :: [Integer]
    take 50 fibs :: [Integer]
    
    x <- take 50 fibs
    x :: Integer
    
    last :: [a] -> a
    last x :: ???
    

    如果您删除 last,您的列表理解将进行类型检查。我认为你的意思更像是

    [ x | x <- takeWhile (<= 4*10^6) $ take 50 fibs, x `mod` 2 == 0 ]
    

    虽然。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-29
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多