:: a -> (a -> b) -> b operator (Haskell)

17

编写Haskell程序时,我发现自己需要这样的操作符。

(|>) :: a -> (a -> b) -> b
(|>) = flip ($)
infixl 0 |>

我认为当将许多函数粘合在一起时,它非常有用。

tText cs = someFun cs   |>
           lines        |>
           map (drop 4) |>
           reverse

我更喜欢使用|>而不是.,因为使用|>时应用函数的顺序与编写函数的顺序相同。

tText' cs = reverse      . 
            map (drop 4) . 
            lines        . 
            someFun $ cs

问题是:这个符号 (|>) 在 Prelude 或其他基本库中已经存在吗?重新实现简单的东西是我想避免的愚蠢行为。

Hoogle 搜索没有帮助。我找到的最接近的东西是 >>>(箭头),但似乎有些过度。


3
不,它没有,尽管正如你所说 >>> 有这个功能。还有一个关于为什么 F# 使用 |> 而 Haskell 使用 .$ 的 SO(StackOverflow)问题,这非常相关。(也要注意,仅供娱乐的是,使用 .>>>,你可以将你的函数写成无需传入参数:tText = reverse . map (drop 4) . lines . someFun 或者 tText = someFun >>> lines >>> map (drop 4) >>> reverse。) - Antal Spector-Zabusky
1
不久前,邮件列表上曾经有一次讨论是否将此项添加到标准库中。http://www.haskell.org/pipermail/libraries/2012-November/018832.html - Dan Burton
4
函数的应用顺序与函数书写顺序相同。这种思维方式是Haskeller所避免的:你不指定“先做这个,然后用结果做那个,然后......”,而是专注于“期望的结果”,因此从最后一个计算步骤开始是非常自然的。此外,由于惰性评估,这个“最后”的步骤实际上将是首先被评估的!对于需要按顺序考虑的流程式函数,Haskell具有单子(Monads),其中do符号始终向前。 - leftaroundabout
找到了这个网址http://hackage.haskell.org/packages/archive/reverse-apply/latest/doc/html/Control-Apply-Reverse.html - user2205541
另外,tText cs = ($ cs) $ someFun >>> lines >>> map (drop 4) >>> reverse - Will Ness
4个回答

16

没有,据我所知标准库里没有这样的东西。很多年前,我的很多代码都导入了我简短但方便的Forwards模块:

> module Forwards where

> infixl 0 |>
> infixl 9 .>

> (|>) = flip ($)
> (.>) = flip (.)

我甚至使用了与你相同的名字!

现在我很少使用它 - 我已经习惯了函数组合所使用的顺序。

随意使用您自己方便的快捷方式。

我现在比以前更少使用 $。 以前我会写

thing = this $ that arg $ an other $ it

现在我写作

thing = this . that arg . an other $ it

12

1
而且,diagrams将其定义为# - Peter Hall

7
您可以将 (|>) 定义为“flip id”,理解此方法为什么有效是 Haskell 中类型推断的一堂精彩课程。

0
就我个人的经验而言,我不知道有这样的库。如果真的存在这样的库,我建议不要使用它。

除非您使用了lens包,否则我建议不要使用那种外部定义的运算符。(在lens包的情况下,您确实需要并已经拥有这样的运算符。)

根据我的经验和个人看法...

在某些情况下,如果正向组合比通常的组合更易读(不仅仅是处理镜头时),则通过该模块或通过letwhere在本地定义特殊运算符会很有益。为此,我倾向于使用单个Unicode符号而不是ASCII组合。

(·) = flip (.)
infixl 1 (·)

(§) = ($) -- left associative, no flip
infixl 0 (§)

几年前(当时还没有镜头),我考虑为这些运算符定义自己的模块。但后来我很少使用该模块,以至于我倾向于重新发明轮子。将这些运算符放在库中甚至可能会增加阅读代码的难度:读者必须查找那些很少使用的运算符。在这种情况下,局部定义的运算符要好得多。


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