【问题标题】:Filter list of lists筛选列表列表
【发布时间】:2011-10-22 17:50:44
【问题描述】:

我对 Haskell 很陌生,才刚刚开始学习它。 我正在使用“Learn You a Haskell for Great Good!”入门教程,并看到解决“3n+1”问题的示例:

chain :: (Integral a) => a -> [a]  
chain 1 = [1]  
chain n  
    | even n =  n:chain (n `div` 2)  
    | odd n  =  n:chain (n*3 + 1)  

numLongChains :: Int  
numLongChains = length (filter isLong (map chain [1..100]))  
    where isLong xs = length xs > 15  

所以,numLongChains 计算所有长度为 15 步的链,对于从 1 到 100 的所有数字。

现在,我想要自己的:

numLongChains' :: [Int]  
numLongChains' = filter isLong (map chain [1..100])
    where isLong xs = length xs > 15    

所以现在,我不想计算这些链,而是返回带有这些链的过滤列表。 但是现在编译时出现错误:

Couldn't match expected type `Int' with actual type `[a0]'
Expected type: Int -> Bool
  Actual type: [a0] -> Bool
In the first argument of `filter', namely `isLong'
In the expression: filter isLong (map chain [1 .. 100])

可能是什么问题?

【问题讨论】:

    标签: list haskell nested-lists


    【解决方案1】:

    numLongChains 的类型签名可能不正确。根据您要执行的操作,需要以下其中一项:

    • 您只是想计算这些链,您的函数numLongChains 显然应该返回一个数字,将第一行更改为length $ filter isLong (map chain [1..100]),将类型更改为Int
    • 您想要返回长链的长度列表。在这种情况下,类型签名很好,但您需要返回一个长度。我建议你,在过滤和过滤之前计算长度。函数的主体变为filter (>15) (map (length . chain) [1..100])
    • 您希望返回所有长度超过 15 个字符的链。只需将签名更改为[[Int]]Ints 的链(列表)列表)就可以了。

    【讨论】:

    • 谢谢!真的是我的错,使用 [[Int]] 解决了问题
    【解决方案2】:

    FUZxxl 是对的。您将希望将函数的类型签名更改为[[Int]]。当您过滤列表列表并仅选择足够长的列表时,您将返回列表列表。

    关于阅读 Haskell 编译时调试器/错误的注意事项。这个错误可能看起来很奇怪。它说你有[a0] -> Bool,但你期待Int -> Bool。这是因为类型检查器假定,根据您的 numLongChains 函数的签名,您将需要一个过滤器函数来检查 Ints 并返回可接受的列表。过滤列表并返回 [Int] 的唯一方法是使用一个函数,该函数接受 Ints 并返回 Bools (Int -> Bool)。相反,它看到了一个检查长度的函数。 Length 需要一个列表,因此它猜测您编写了一个检查列表的函数。 ([a0] -> Bool)。有时,检查器并不像您希望的那样友好,但如果您仔细观察,您会发现 10 次中有 9 次,难以破译的错误是诸如假设的结果。

    【讨论】:

    • Erik,也谢谢你,但我只知道现在对我来说太难了 :) 关于我从命令式语言中了解到的隐式转换的邪恶
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    相关资源
    最近更新 更多