我正在尝试在对列表上使用find函数,我想找到第一个元素等于x的第一对,所以我写道:
find (x == fst) list
由于fst
函数缺少一个参数,我认为(x == fst)
将是一个接受元组并返回布尔值的函数,但编译器会将其解释为布尔值,就好像{{1是一个变量。也许fst
被解释为一个函数?但这不是要求它被()包围吗?
我确实使用列表理解来解决问题,但我仍然很好奇如何使用find来解决它。
答案 0 :(得分:5)
(==)
的类型为x -> x -> Bool
。在您的情况下,键入x
为(a, b) -> a
。这是因为其中一个操作数是fst
,它具有该类型。因此,您的(==)
类型为((a, b) -> a) -> ((a, b) -> a) -> Bool
。也就是说,(==)是一个比较两个函数x和fst的函数。
你想要的是撰写 fst
和(==)
。例如,(\y -> (x == fst y)
。这是一个函数,它接受一个元组y
,并检查x
是否等于它的第一个值。
有一个函数可以为您组合函数(.)
。它需要两个函数f(x)和g(x),并返回另一个函数f(g(x))。您可以将此功能用于您的程序,如下所示:find ((x ==) . fst) list
。
比较以下程序,第一个编写为lambda函数,第二个编写函数组合运算符:
(\y -> (x == fst y)
-- Compared to:
(x ==) . fst
要点:
(==)正在比较两个函数x和fst,并返回一个Bool。
你想要的是一个函数,它接收一个元组,从中获取第一个项目,并将它与x进行比较。这可以通过功能组合来完成。
答案 1 :(得分:3)
如果要将变量传递到特定位置,请使用lambda函数:
(\ y -> x == fst y)
否则,编译器不知道您希望插入变量的具体位置。
如果您的函数调用一个函数,您可以使用currying来进行快捷方式。但对于复杂的表达式,这不起作用。你不能只是在表达式中留下最后一个术语并期望它起作用。它仅适用于单一功能。
另一种方法是使用函数(x ==)
和函数fst
并将它们与(.)
运算符链接起来:
((x ==) . fst)
这是一个“更好”的个人品味问题。 (没有性能差异;唯一的区别是源代码的样子。)