通过使用点和美元来丢弃变量

时间:2017-06-04 09:10:41

标签: haskell

我是Haskell初学者,我想知道为什么我们可以在使用某些运算符时丢弃某些变量,例如:

     last xs = head (reverse xs)
     last'   = head . reverse

另一个例子:

     example p xs = length (filter p xs)
     example' p = length . filter p

为什么我们不能在这个函数中抛出p?

2 个答案:

答案 0 :(得分:6)

你没有“丢弃”那里的变量,你只是不提及它们。该过程称为eta-conversion:由于引用透明度,在您定义

g x = f x

你也可以简单地写g = f。当f不是命名函数(如

)时,这也有效
last' xs = (head . reverse) xs
 ⇒ last' =  head . reverse

但是这要求变量实际上只作为自包含函数的最终参数出现,例如:已经命名或包含在parens中的一个。例如,使用原始last这是不可能的,因为xs在括号(reverse xs)中出现,因此您首先需要转换head (reverse xs) ≡ (head . reverse) xs在你能减少它之前。同样地,

length . filter p ≡ length . (filter p)

所以你不能只减少p,因为它在括号内。但是,正如bereal所建议的那样,您可以将预合成(length .)视为应用于表达式其余部分的单独函数:

length . filter p
  ≡ (length .) (filter p)
  ≡ ((length .) . filter) p
example' = (length .) . filter

但我同意这会使代码更难阅读,因此我通常会保留example'原样。

答案 1 :(得分:3)

这称为point-free notation。例如,它是:

example' = (length .) . filter

虽然在我看来很难理解。

有一个方便的工具可以生成无点版本:pointfree.io