1.5 KiB
Most commonly used Infix Operators have flipped variants, e.g.
- Functions#Composition has
g <<< f
orf >>> g
- function application has
f $ a
ora # f
- Functor has
f <$> a
ora <#> f
- Bind has
f =<< m
orm >>= f
In general, right-to-left operators tend to be easier to refactor into & out of because they closely mirror the expressions they replace:
map (add 1) maybeNum
-- into
add 1 <$> maybeNum
foo (bar a)
-- into
foo <<< bar
Left-to-right, on the other hand, can read better to humans and plays better with pipelines containing both [[Bind|bind >>=
]] and [[Functor|map <#>
]].
Consider an expression piping Maybe String
to split :: String -> Array String
then Data.Array.NonEmpty.fromArray :: Array a -> Maybe (NonEmptyArray a)
, then toLower
each element:
String.toLower
<$> (
Array.NonEmpty.fromArray
=<< String.split "."
<$> mStr
)
We need to wrap the right hand of the last map
because the precedence of =<<
is 1
(the lowest) and the precedence of <$>
is 4
.
Written RTL, though, gives:
mStr
<#> String.split "."
>>= Array.NonEmpty.fromArray
<#> String.toLower
This works because <#>
's Precedence (1) is the same as >>=
. The lower precedence on flipped map means you'll often need more parentheses wrapping its arguments (..) <#> (..) >>= (..)
as opposed to entire expressions .. <$> (.. =<< ..)
.
Personally, I try to stick to RTL except for expressions including bind.