在 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
我来自 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