【问题标题】:Point free style with infix notation带中缀符号的无点样式
【发布时间】:2018-06-14 08:02:34
【问题描述】:

您好,在使用中缀表示法时有没有办法编写无点样式?

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) `+`

你不能像 e.g 那样以无点风格组合运算符吗?

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

我的意思是你可以砍掉像 fold 这样的函数的参数,但为什么不能去掉操作符的参数呢?

【问题讨论】:

  • 你的意思是完全没有积分吗?您给出的唯一完全无意义的示例是最后一个。
  • 是的,你能做到完全无积分吗?
  • 你打算最后三个例子做什么?根据类型签名,它们只需要 2 个参数。
  • 我编辑了对不起!

标签: haskell pointfree


【解决方案1】:

既然你需要传递两个参数,我们可以使用所谓的“surprised owl operator”。这基本上是参数的组合。所以我们可以使用:

f = <b>((.).(.))</b> (+) (+)

或者我们可以更内联操作符,例如:

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

猫头鹰运算符((.).(.)) f g基本上是\x y -&gt; f (g x y)的缩写

这是如何工作的?

surprise owl operator”的规范形式是:

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

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

(\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)

所以基本上这意味着我们惊讶的 owl 运算符等于:

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)

【讨论】:

  • 感谢您的回答!
【解决方案2】:

您必须将(+)(+) 组合两次,才能完全无点: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 这样的函数的无点定义。

当您像这样从“结束”中“省略”多个参数时,您通常必须编写多次。使用一些类似的函数应该有助于建立对此的直觉。

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

【讨论】:

  • 谢谢您的回答先生!
猜你喜欢
  • 2012-05-01
  • 2020-05-09
  • 2019-10-28
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
相关资源
最近更新 更多