2017-06-04 12 views
0

的我是一个Haskell初学者,我想知道为什么我们可以使用某些运营商时,放弃某些变量,例如:丢弃变量通过使用点和美元

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

又如:

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

为什么我们不能在这个函数中折腾p?

+0

'.'运算符被称为“合成”。 '$'被称为“应用程序”。并置,例如'f x',也是应用程序。如果你搜索运营商名称,你应该找到很好的解释。 – sapanoia

+0

可能重复[如何使多个eta减少haskell](https://stackoverflow.com/questions/26538438/how-to-make-multiple-eta-reductions-in-haskell) – amalloy

回答

3

这叫做point-free notation。对于你的例子,它是:

example' = (length .) . filter 

虽然它很难领会,在我看来。

有一个生成自由点版本的方便的工具:pointfree.io

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因为它是一个括号内。但是,您可以为变成真正的建议,考虑precomposition (length .)做为所应用到表达式的其余部分一个单独的功能:

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

但我同意,这使得代码,而难以阅读,所以我通常保留原来的example'

+0

对于第一段,我没有看到参考透明度如何相关(在这个具体情况下)。 –

+0

@AlexeyRomanov:https://tio.run/##Zc5dC8IgFAbge3/[email protected]@[email protected]/zW8A2ciXxKVzHlg2AjA32HeDAGga0LGrg1aD1AqwDxfoEQzJ81hmWlGu15AzyKhhbUmu3cnTDZQXFx9sv9gu/NorLzyl9AA – leftaroundabout

+0

或者如果你喜欢的Python https://tio.run/##XctBCsMgFITh/TvFkBLQQiE2u0Jv0o2pPg00GsSCPb2J0C7S5fwfs36yj2GslQfc8dLLZDTKDeV8JVZ/[email protected]zB @tTVnrBg – leftaroundabout