使用过滤器的初学者类型错误

Typ*_*mao 6 haskell

我刚刚开始使用 Haskell,我遇到了你们大多数人可能会认为是初学者的错误。

考虑一个元组列表 myTupleList = [(3,6),(4,8),(1,3)]

好的。我写了这个函数来返回元组列表,其中第一个元组中的第二个元素是第一个元素的两倍:(例如使用 myTupleList: double myTupleList ,它返回 [(3,6),(4,8)] )

double [] = []
double (x:xs)
   |(snd x) == 2 * (fst x) = x: double xs
   |otherwise              = double xs
Run Code Online (Sandbox Code Playgroud)

现在我确定这不是世界上最漂亮的功能,但它确实有效。现在的问题是使其适应使用过滤器。这是我目前的尝试:

double [] = []
double xs = filter ((2 * (fst(head xs))) == (snd(head xs))) xs
Run Code Online (Sandbox Code Playgroud)

我不明白的是,过滤器接收两个参数:一个布尔表达式和一个列表。但是,我收到以下错误:

Couldn't match expected type ‘(a, a) -> Bool’
              with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
  In the first argument of ‘filter’, namely
    ‘((2 * (fst (head xs))) == (snd (head xs)))’
  In the expression:
    filter ((2 * (fst (head xs))) == (snd (head xs))) xs
  In an equation for ‘double’:
      double xs = filter ((2 * (fst (head xs))) == (snd (head xs))) xs
• Relevant bindings include
    xs :: [(a, a)] (bound at Line 9, Column 8)
    double :: [(a, a)] -> [(a, a)] (bound at Line 8, Column 1)
Run Code Online (Sandbox Code Playgroud)

我确信这只是 Haskell 作为一种我不习惯或不正确理解的函数式语言的一些愚蠢的错误或限制,但是在这方面获得一些帮助会很棒。

谢谢

Wil*_*sem 5

filter期望一个函数a -> Bool,但(2 * (fst(head xs))) == (snd(head xs))不是一个将元素映射到 a 的函数Bool,而只是 a Bool。在这里使用没有多大意义head x,您使用参数来“访问”元素:

double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double xs = filter (\x -> 2 * fst x == snd x) xs
Run Code Online (Sandbox Code Playgroud)

您可以使用模式匹配来解包 2 元组,因此不再需要fstand snd。此外,您可以执行?-reduction,从而在这种情况下xs同时删除头部和主体double:

double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (\(a, b) -> 2 * a == b)
Run Code Online (Sandbox Code Playgroud)

这给了我们:

Prelude> double [(3,6),(4,8),(1,3)]
[(3,6),(4,8)]
Run Code Online (Sandbox Code Playgroud)

我们甚至可以使谓词无点:

double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (uncurry ((==) . (2 *)))
Run Code Online (Sandbox Code Playgroud)