filter ((>4).(length snd)) lst
看起来您对此有正确的想法,但正如您所注意到的,它无法编译。尽管当我尝试时,该错误与您提到的关于 length 有太多参数的错误不同 - 您在这里给了它一个参数,这是正确的数字。但是,您给它的参数是一个函数(snd,它为您提供一对中的第二个元素),并且它需要一个列表 - 因为无法将函数视为列表,编译器会拒绝这毫无意义。 (即使这不是问题,length snd 会导致 Int,并且您不能将其用作 . 运算符的参数,它需要在任一侧使用函数。这就是 GHC实际上在我尝试运行您的代码时抱怨:Couldn't match expected type '([Char], [Char]) -> Integer' with actual type 'Int' In the second argument of '(.)', namely '(length snd)')
@WillemVanOnsem 已经向您展示了如何修复它,所以让我们来看看。确实和你的很像:
filter ((>4) . length . snd)) lst
. 运算符,您似乎知道,首先将函数应用到其右侧,然后将其左侧的函数应用于结果。所以表达式(>4) . length . snd 的意思是,给定一对,取第二个元素,然后取它的长度(假设它是一个列表,否则不会编译),然后检查结果数字是否大于 4。换句话说,(>4) . length . snd) 是(a, [b]) -> Bool 类型的谓词,它告诉您该对的第二个槽中的列表是否有超过 4 个元素。 [术语“谓词”仅表示任何返回 Bool 的函数 - 它是应用于您感兴趣类型的元素的测试,如在 filter 和许多相关函数中使用的那样。] 这当然是你的目标是什么。
总而言之,您的答案与正确答案之间的唯一区别在于length snd(将snd 函数作为length 的参数,这是毫无意义的)和length . snd(通过首先应用snd,然后将length 应用于其结果给出的函数)。它们可能看起来很相似,但它们实际上意味着非常不同的东西。
我相信,通过更多的练习,您将能够自己完成类似的事情,并理解 GHC 在出现编译错误时会告诉您什么。
(PS:您的代码实际上首先失败了,因为a、rr 等是您没有绑定到任何值的变量。我假设它们都是字符串,尤其是当您提到获取 r..r 值的长度时 - 在这种情况下,它们需要用双引号括起来:("a", "rr") 等等。