Haskell的$运算符是否有一个反向运算符?

44
在Haskell中是否有类似于美元符号的操作符,但是它会优先处理左侧的表达式?也就是说,代替像这样使用dollar符号:
f (x 1) 

被编写为

f $ x 1

我想把它写成

x 1 $ f

这纯粹是一种样式上的事情。我按顺序运行一系列函数,如果我能够从左到右编写它们以匹配我的阅读方式,那将会很好。是否有这样一个运算符?

[更新] 有几个人问我是否不能定义自己的。答案是,我想在重新发明轮子之前检查是否存在现有的运算符。


6
这类似于 F# 的管道组合运算符。相关讨论(为什么它没有被内置到 Haskell 中):https://dev59.com/THM_5IYBdhLWcg3wQQtd - Tim Robinson
看起来我的问题的答案是“不”。谢谢 :) - Benjamin Confino
2
你意识到你在同一个表达式中结合了从左到右和从右到左的应用,对吧?我想大多数人都会感到不适。反向应用被称为T组合器。几年前它经常用(#)表示,但现在#是GHC中的特殊符号,所以它不再被广泛使用。 - stephen tetley
你想要的是:f(g 1)。为什么不直接写成 f.g $ 1 呢? - demi
@demi 我认为 OP 想要用从左到右的管道表达 f(g 1)。f . g $ 1 是相反的。 - dopatraman
6个回答

48

36
在 Haskell 中,你可以使用 flip 来改变任意二元函数或运算符的参数顺序:
ghci> let (|>) = flip ($)
ghci> 3 |> (+4) |> (*6)
42

4
它是否保持相同的运算符优先级? - Filip Haglund

21

我不知道是否存在标准运算符,但是什么阻止你自己编写一个呢?在ghci中可以这样实现:

Prelude> let a $> b = b a
Prelude> 1 $> (+2)
3
Prelude> sum [1, 2] $> (+2)
5
Prelude> map (+2) [1, 2] $> map (+3)
[6,7]

更新:在hoogle上搜索a -> (a -> b) -> b(这是此操作符的类型)没有找到有用的内容。


4
似乎我会使用这个,谢谢。一个英镑的操作员对我很有吸引力。 - Benjamin Confino
5
双关语总是很有趣,但对于实际使用,我建议考虑使用 |>。如上所述,在 F# 中,该运算符正好可以实现你想要的功能,因此使用相同的名称将有助于人们更容易地理解你的代码。 - C. A. McCann
2
Haskell 的一个真正的优势在于你可以编写自己的控制流操作符。Haskell 没有“循环”结构?没问题!只需编写您自己的即可。 - Sean Seefried
Data.Sequence 使用 |> 符号。使用 # 符号似乎更好。 - michau
链接:[Hoogle搜索“a ->(a-> b)-> b”](http://www.haskell.org/hoogle/?hoogle=a+-%3E+%28a+-%3E+b%29+-%3E+b)。该精确类型的唯一结果是[`($)`](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:-36-)和[`($!)`](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:-36--33-)。 - Rory O'Kane

10

这个组合子(半开玩笑地)在data-aviary包中定义:


Prelude Data.Aviary.BirdsInter> 1 `thrush` (+2)
Loading package data-aviary-0.2.3 ... linking ... done.
3

虽然实际使用那个包有些荒谬,但阅读源代码是有趣的,并揭示了这个组合子是通过神奇的咒语flip id(或者在鸟类学语境下,cardinal idiot)形成的。


4
"caridinalIdiot"是一个很棒的组合名称! - sclv

4

我不知道是否有任何标准版本,但我在一些地方看到过(#)被用于这个目的。特别是 HOC(Higher-Order Component)中使用了像这样的习语:

someObject # someMessage param1 param2

我记得看到其他“面向对象”的库也使用#运算符,但是不记得有多少个或哪些。


2
Wash使用了(#)。Erik Meijer、Daan Leijen和James Hook使用它来使用Active Haskell(一个Haskell-COM桥)脚本化MS Agent。可能最初的Haskell/ObjectiveC桥也使用了(#)。 - stephen tetley

-1

你不能重新定义$吗?

let ($) x f = f x

或者选择不同的运算符,比如$$


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接