Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I come from Scala. So I frequently do stuff like:

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

In Haskell, after I discovered I can get rid of all the nested parenthesis using $ and ., I recently found myself writing:

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

Now, this works, but the code reads right-to-left, and unless I shift to Arabic, this is difficult for me to reason about.

Is there any other trick that makes me chain the functions from left to right? Or this is just the Haskell idiomatic way?

like image 229
sscarduzio Avatar asked Nov 08 '15 11:11

sscarduzio


3 Answers

Unfortunately, it's the Haskell idiomatic way. But the & operator might do what you want.

import Data.Function ((&))

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

Essentially, (&) = flip ($). Likewise, Control.Arrow.(>>>) = flip (.)

UPDATE (6+ months later): I have to admit, this issue is a big source of frustration for me and I have been toying with this potential solution:

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

like image 71
obadz Avatar answered Oct 05 '22 22:10

obadz


Yes, it is idiomatic Haskell. Not Arabic, but rather Mathematic, derived from the syntax for composition. See also Haskell composition (.) vs F#'s pipe forward operator (|>).

Still, even in Haskell you sometimes prefer to write your calls in the other direction, and you'll find a few libraries (e.g. Data.Function since base 4.8.0) who have defined

(&) = flip ($)

so that you can express your call as

[1..10] & filter (< 3) & map (**2) & show & putStrLn
like image 36
Bergi Avatar answered Oct 05 '22 23:10

Bergi


Why not make a new operator?

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

Now you can just write

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

This is the equivalent of the (&) operator from Data.Function.

like image 45
AJF Avatar answered Oct 05 '22 22:10

AJF