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?
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
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
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With