在 Haskell 中从左到右链接方法(与从右到左相反)

Chaining methods left to right in Haskell (as opposed to right to left)

我来自 Scala。所以我经常做这样的事情:

println((1 to 10).filter(_ < 3).map(x => x*x))

在 Haskell 中,在我发现可以使用 $. 摆脱所有嵌套括号后,我最近发现自己在写:

putStrLn . show . map (**2) . filter (< 3) $ [1..10] 

现在,这行得通,但是代码是从右到左读取的,除非我换成阿拉伯语,否则我很难理解。

还有其他技巧可以让我从左到右链接函数吗?或者这只是 Haskell 惯用的方式?

为什么不创建一个新的运算符?

(#) :: a -> (a -> b) -> b
(#) = flip id

现在你可以写

[1..10] # filter (< 3) # map (**2) # show # putStrLn

这相当于 Data.Function 中的 (&) 运算符。

不幸的是,这是 Haskell 惯用的方式。但是 & 运算符可能会做你想做的事。

import Data.Function ((&))

[1..10] & filter (< 3) & map (**2) & show & putStrLn

本质上,(&) = flip ($)。同样,Control.Arrow.(>>>) = flip (.)

更新(6 个多月后): 我不得不承认,这个问题让我很沮丧,我一直在研究这个潜在的解决方案:

https://gist.github.com/obadz/9f322df8ba6c8a9767683d2f86af8589#file-directionalops-hs-L81

是的,这是惯用语 Haskell。不是阿拉伯语,而是数学,源自组合语法。另见 Haskell composition (.) vs F#'s pipe forward operator (|>)

尽管如此,即使在 Haskell 中,您有时更喜欢在另一个方向编写调用,并且您会发现一些库(例如 Data.Function 自 base 4.8.0 以来)定义了

(&) = flip ($)

这样您就可以将您的电话表达为

[1..10] & filter (< 3) & map (**2) & show & putStrLn