我正在尝试使用大于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)] |
答案 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)