过滤列表清单

问题描述:

我对Haskell很新,只是开始学习它。 我正在使用“学习你一个伟大的好事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]) 

可以采取什么问题吗?

numLongChains的型号签名可能不正确。根据你想要做什么,下面的一个需要:

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

谢谢!真的是我的错,用[[Int]]解决了问题 – dmitry

+0

@dmitry请接受这个答案来帮助别人。只需点击答案评分下方的绿色勾号即可。 – fuz

FUZxxl是正确的。您将要将您的功能的类型签名更改为[[Int]]。由于您正在筛选列表并只选择足够长的列表,因此您将返回列表列表。

关于阅读Haskell编译时调试器/错误的一个注意事项。这个错误看起来很奇怪。它说你有[a0] -> Bool但你期待Int -> Bool。这是因为类型检查器假定,从您的numLongChains函数的签名中,您将需要一个筛选函数来检查Ints并返回可接受的列表。对列表进行过滤并获取[Int]的唯一方法是获取一个需要Int s并返回Bool s (Int -> Bool)的函数。相反,它会看到一个检查长度的函数。长度需要一个列表,所以它猜测你写了一个函数来检查列表。 ([a0] -> Bool)。有时候,检查者并不像你期望的那么友善,但是如果你看起来足够努力,你会看到10次中有9次,难以辨认的错误是诸如假设的结果。

+0

Erik,也谢谢你,但我所知道的是,现在对我来说太难了:)而且关于我从命令式语言中知道的隐式转换的邪恶 – dmitry