使用中缀表示法指向自由风格

时间:2018-06-14 08:02:34

标签: haskell pointfree

使用中缀表示法时,有没有办法写点免费样式?

f::Int->Int->Int->Int
f a b=(+) (a+b)

为什么你不能做这样的事情?

 f::Int->Int->Int->Int
 f a b=(a+b) +

      or

 f a b= (a+b) `+`

你能不能像点那样组合点自由风格的运算符吗?

ptfree::Int->Int->Int->Int
ptfree=(+) (+)

我的意思是你可以删除像fold这样的函数的参数,但为什么不对运算符参数?

2 个答案:

答案 0 :(得分:3)

您必须将(+)f = ((+) .) . (+)一起撰写两次,以使其完全无点:(f . g) x = f (g x)

回想一下,作文被定义为

(f . g) = \x -> f (g x)

或等同于:

f = ((+) .) . (+)

因此,如果您查看合成(.)并使用f = ((+) .) . (+) f = \x -> ((+) .) ((+) x) -- definition of (.) f = \y -> (\x -> (+) (((+) x) y)) -- definition of (.) f x y = (+) (((+) x) y) -- a simpler way to write this f x y z = (+) (((+) x) y) z -- explicitly add in the final argument (eta expansion) f x y z = ((+) x y) + z -- rewrite as infix f x y z = (x + y) + z -- rewrite as infix 的定义向后工作:

f

你知道我们在尝试使它成为无点之前我们最终得到了什么,所以我们知道这个定义是有效的。从上面的步骤开始,大致从下到上,可以让您了解如何找到像toy这样的函数的无点定义。

当你像这样从“结束”“离开”多个参数时,你通常必须多次复合。通过一些类似的功能应该有助于为此建立直觉。

注意:我一般不建议在生产代码中使用这种无点(当它使事情变得复杂时)。

答案 1 :(得分:3)

因为你需要传递两个参数,我们可以使用所谓的“惊讶的猫头鹰操作符”。这基本上是参数的组合。所以我们可以使用:

f = ((.).(.)) (+) (+)

或者我们可以更像内联运营商:

f = ((+) .) . (+)

猫头鹰操作符((.).(.)) f g基本上是\x y -> f (g x y)

的缩写

这是如何运作的?

惊讶的猫头鹰操作员”的规范形式是:

= ((.) . (.))
------------- (canonical form)
  (.) (.) (.)

所以我们现在可以用相应的lambda表达式替换(.)

(\f g x -> f (g x)) (.) (.)

现在我们可以执行一些替换:

   (\f g x -> f (g x)) (.) (.)
-> (\x -> (.) ((.) x))
-> (\x -> (\q r y -> q (r y)) ((.) x))
-> (\x -> (\r y -> ((.) x) (r y)))
-> (\x r y -> ((.) x) (r y))
-> (\x r y -> ((\s t u -> s (t u)) x) (r y))
-> (\x r y -> (\t u -> x (t u)) (r y))
-> (\x r y -> (\u -> x ((r y) u)))
-> \x r y u -> x ((r y) u))
-> \x r y u -> x (r y u)

所以基本上它意味着我们惊讶的猫头鹰操作员,等于:

surprised_owl :: (y -> z) -> (a -> b -> y) -> a -> b -> z
surprised_owl f g x y = f (g x y)  -- renamed variables

如果我们现在专注于提供的功能(两次(+)),我们得到:

f = surprised_owl (+) (+)

这样:

f x y = (+) ((+) x y)