过滤列表清单

时间:2011-10-22 17:50:45

标签: list haskell nested-lists

我对Haskell很新,只是开始学习它。 我正在使用“让你学习哈斯克尔的伟大成就!”开始教程,看到解决“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])

可能是什么问题?

2 个答案:

答案 0 :(得分:3)

numLongChains的类型签名可能不正确。根据您的要求,需要满足以下条件之一:

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

答案 1 :(得分:1)

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

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