为什么我的谓词被解释为布尔值? (Haskell的)

时间:2018-04-27 06:59:43

标签: haskell compiler-errors find predicate

我正在尝试在对列表上使用find函数,我想找到第一个元素等于x的第一对,所以我写道:

find (x == fst) list

由于fst函数缺少一个参数,我认为(x == fst)将是一个接受元组并返回布尔值的函数,但编译器会将其解释为布尔值,就好像{{1是一个变量。也许fst被解释为一个函数?但这不是要求它被()包围吗?

我确实使用列表理解来解决问题,但我仍然很好奇如何使用find来解决它。

2 个答案:

答案 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)

这是一个“更好”的个人品味问题。 (没有性能差异;唯一的区别是源代码的样子。)