17

Writing Haskell programs I found myself in need of an operator like this.

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

I think it is useful when glueing many functions together.

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

I prefer it over . because with |> the order in which the functions are applied is the same as the order in which the functions are written.

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

Question is: is this (|>) something that already exists in the Prelude / some other basic library? Reimplementing simple stuff is something silly which I would like to avoid.

A Hoogle search did not help. Closest thing I found was >>> (Arrows), but it seems an overkill.

mklement0
  • 382,024
  • 64
  • 607
  • 775
user2205541
  • 173
  • 5
  • 3
    No, it doesn't, although as you say `>>>` does. [There was another SO question about why F# uses `|>` where Haskell uses `.` and `$`, which is pretty relevant.](http://stackoverflow.com/questions/1457140/haskell-composition-vs-fs-pipe-forward-operator) (Note also, just for fun, that with `.` or `>>>`, you can write your function point-free: `tText = reverse . map (drop 4) . lines . someFun`, or `tText = someFun >>> lines >>> map (drop 4) >>> reverse`.) – Antal Spector-Zabusky Mar 24 '13 at 21:49
  • 1
    Some time ago, there was a conversation on the mailing list about adding this to the standard libraries. http://www.haskell.org/pipermail/libraries/2012-November/018832.html – Dan Burton Mar 24 '13 at 22:44
  • 4
    "the order in which the functions are applied is the same as the order in which the functions are written."   Well – that's the kind of thinking Haskellers avoid: you don't specify "do this, then with the result do that, then..." but focus on the _desired result_, so it's perfectly natural to start with the last calculation step. Also, what with lazy evaluation, this "last" step will actually be the first to be evaluated! — For the procedural kind of functions, the ones where you actually need to think in sequential steps, Haskell has Monads, whose `do` notation is always "forwards". – leftaroundabout Mar 24 '13 at 23:37
  • Found this http://hackage.haskell.org/packages/archive/reverse-apply/latest/doc/html/Control-Apply-Reverse.html – user2205541 Mar 25 '13 at 08:56
  • also, `tText cs = ($ cs) $ someFun >>> lines >>> map (drop 4) >>> reverse` – Will Ness Mar 26 '13 at 18:37

4 Answers4

16

No, there isn't anything in a standard library that I know of. Years and years ago a lot of my code imported my breif but handy Forwards module:

> module Forwards where

> infixl 0 |>
> infixl 9 .>

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

I even used the same name as you!

These days I don't use it much at all - I got used to the order that function composition uses.

Feel free to use your own handy shortcuts.

I also use $ less than I used to. Where I used to write

thing = this $ that arg $ an other $ it

Now I write

thing = this . that arg . an other $ it
AndrewC
  • 32,300
  • 7
  • 79
  • 115
12

The lens library defines this operator as &.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
John Wiegley
  • 6,972
  • 1
  • 16
  • 20
7

You can also define (|>) as "flip id", and understanding why this works is a great lesson in type inference by unification as used in Haskell.

pmk
  • 71
  • 1
0

As far as my experience goes, I don't know any such library. And if such a library exists, I'd advise against using it.


Unless you are using the lens package, I'd suggest not to use externally defined operators of that kind. (In case of that lens package, you really need and already have such an operator.)

In my experience, IMHO and such ...

In cases where the readability enhances with a forward composition in contrast to the usual composition (not only when dealing with lenses), it is beneficial to define a special operator in that module or locally via let or where. For that, I tend to use single unicode symbols rather than ascii combos.

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

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

Some years ago(, when there were no lenses), I thought of defining my own module for these, too. But then I grow to use that module sooo infrequent that I tended to reinvent the wheel anyway. To have these operators in a library may even increase the effort of reading the code: The reader has to look those rarely used operators up. In that case, locally defined operators are way better.

comonad
  • 5,134
  • 2
  • 33
  • 31