Haskell functions left-to-right

Go To StackoverFlow.com

18

I have a function that I use quite frequently, which allows me to write my code in a way which seems more natural to me.

infixl 6 $:
($:) :: a -> (a -> b) -> b
a $: f = f a

This lets me do something like

let x = getData
        $: sort
        $: group
        $: aggregate

instead of

let x = aggregate 
        $ group 
        $ sort 
        $ getData

I recently learned that Clojure has something like this built in (I don't know much Clojure, but I think it would be written (-> getData sort group aggregate)?) which makes me wonder if Haskell has it built in as well. Hoogle doesn't have any results though.

Are there any standard libs with something similar included? It probably makes my code hard for others to read if I have such a common part is idiosyncratic.

2012-04-04 01:27
by Xodarap
My preference is to call this operation # as per OOHaskell, since it is fundamentally the same operation as method selection on objects and the # is the operator used for this in OCaml. Alternatively, copying F# we could use |>Philip JF 2012-04-04 01:58
Diagrams uses # it as well - Long 2012-04-06 17:04
There was a proposal for introducing flip ($) to Data.Function, but it was dropped because no consensus could be reached on whether such a thing would be useful (opposed to confusing to beginners etc.) to have. Here's the discussion: http://markmail.org/message/vsplpb7aajp7goqo?q=pytho - David 2012-12-10 10:32
Could you accept Yoann B.'s answer? The <code>&</code> operator is by now pretty widely used (presumably, mostly thanks to the highly influential lens library, which includes it in its standard coding style) - leftaroundabout 2018-02-06 23:35


22

There's nothing like this built in, but Control.Category.(>>>) is close: it's flip (.), so you can write

f x = x $: sort $: group $: aggregate

as

f = sort >>> group >>> aggregate

There's no shortage of definitions and names for your ($:) combinator. I think functions tend to suit the pipeline style more often than simple applications, so I don't feel any great need for it; (>>>) is a bit ugly, though.

(Besides, Haskell's non-strict semantics mean that the flow of data isn't necessarily in the direction the arrows are pointing here; after all, aggregate could provide the first constructor before sort even gets a chance to look at the argument. So I tend to just use (.) and ($); I'm used to the order.)

2012-04-04 01:32
by ehird
Ugly or not I think (>>>) is intuitive because it looks like (>>=), which is a similar left-to-right pipeline - amindfv 2012-04-04 04:00
Too bad it's flip (.) instead of flip ($). But I guess >>> is as close as you can get - Xodarap 2012-04-04 18:26
There's also (#) from http://hackage.haskell.org/packages/archive/diagrams-lib/0.4.0.1/doc/html/Diagrams-Util.html , but it has a far different infix precedence than ($) - mgsloan 2012-04-12 10:35


3

The reverse application operator your are describing is now part of the standard package base (since 4.8.0) as the & operator.

Note that this operator is defined with a lower precedence than the one you proposed (infixl 1).

2016-04-15 14:07
by Yoann B.


1

There is a library called Flow (https://hackage.haskell.org/package/flow-1.0.10/docs/Flow.html) available in Hackage, created by Taylor Fausak for this exact demand.

It uses the |> operator (inspired from F#) to act as a thread-last.

For eg:

3 |> succ |> recip |> negate
-0.25
2018-02-06 13:59
by Abhiroop Sarkar