自定义元组

时间:2017-11-09 18:21:43

标签: haskell

我正在尝试使用大于d3的a参数值编写一个函数来过滤表单((d1,d2),d3)中的自定义元组列表。

filterTuple 1.5 [((1.0,2.0),1.0),((3.0,5.0),2.0),((4.0,5.0),2.0)]应该返回[((3.0,5.0),2.0),( (4.0,5.0),2.0)]

filterTuples :: Double ->[((Double, Double), Double)] -> [((Double, Double), Double)] 
filterTuples val [((d1,d2),d3)] = filter (d3 < val) [((d1,d2),d3)]

这会使用d3 < val中的表达式抛出下面的错误,而在那里写什么是正确的?

x8.hs:54:47: error:
• Couldn't match expected type ‘((Double, Double), Double) -> Bool’
              with actual type ‘Bool’
• Possible cause: ‘(<)’ is applied to too many arguments
  In the first argument of ‘filter’, namely ‘(d3 < value)’
  In the expression: filter (d3 < value) [((d1, d2), d3)]
  In an equation for ‘filterTuples’:
      filterTuples value [((d1, d2), d3)]
        = filter (d3 < value) [((d1, d2), d3)]    |   

1 个答案:

答案 0 :(得分:4)

您在这里写的是模式匹配,匹配列表与一个元素。你写道:

filterTuples val [((d1,d2),d3)] = ...

所以这意味着一个包含一个元素的列表:一个元组((d1,d2),d3)。这是如何过滤列出任意数量的元素。

我们可以将其写为l

filterTuples val l = ...

但是现在我们仍然需要写一个filter filter :: (a -> Bool) -> [a] -> [a] 函数需要函数a -> Bool作为参数,该谓词应决定要保留哪些元素。

因此我们必须设计这样的功能。我们可以将其写为 lambda表达式

\((d1,d2),d3) -> d3 < val

所以现在我们可以把它写成:

filterTuples :: Ord a => a -> [((b,c),a)] -> [((b,c),a)]
filterTuples val l = filter (\((d1,d2),d3) -> d3 < val) l

现在我们仍然可以改进它。例如,我们可以执行 eta reduction :消除子句的头部和主体中的变量:

filterTuples :: Ord a => a -> [((b,c),a)] -> [((b,c),a)]
filterTuples val = filter (\((d1,d2),d3) -> d3 < val)

我们仍然可以改进它。例如,不清楚为什么要仅使用元组作为第一个元素来过滤元组。为什么不将它推广到所有可能的2元组?

filterTuples :: Ord a => a -> [(d,a)] -> [(d,a)]
filterTuples val = filter (\(dx,d3) -> d3 < val)

我们通常也会使用下划线(_)编写我们不关心的变量:

filterTuples :: Ord a => a -> [(d,a)] -> [(d,a)]
filterTuples val = filter (\(_,d3) -> d3 < val)