When working with Unison code, you might encounter the followingoperatorswhich are provided by thebase
library. They are commonly used for manipulating the order in which a function is applied to its arguments.
a<<
b
<<
b<< : (b ->{𝕖} c) -> (a ->{𝕖} b) -> a ->{𝕖} c
<<
,also known as "compose," takes in two functionsb -> c
anda -> b
and returns a function froma -> c
.
composeEx : Nat -> Boolean
composeEx = Boolean.not << Nat.isEven
Piping multiple functions together with the compose operator looks like:
composeMultiEx : Text -> Boolean
composeMultiEx : Text -> Boolean
composeMultiEx = Boolean.not << Nat.isEven << Text.size
The expression is actually parsed:
((Boolean.not << Nat.isEven) << Text.size)
Giving us a function that expectsText.size
'sargument ofText
and returning the final result of applying theBoolean.not
function.
a>>
b
>>
b>> : (a ->{𝕖} b) -> (b ->{𝕖} c) -> a ->{𝕖} c
>>
,also known asandThen
,is likecompose
with the function argument order reversed. It takes in two functionsa->b
andb->c
and returns a function froma->c
.
andThenEx : Boolean
andThenEx = ((>>) Nat.isEven Boolean.not 4)
Piping together multiple>>
calls looks like:
andThenMultiEx : Boolean
andThenMultiEx = ((>>) (Text.size >> Nat.isEven) Boolean.not "Boo")
a|>
b
|>
b|> : a -> (a ->{𝕖} b) ->{𝕖} b
While>>
returns a function,|>
allows us to apply an argument to a function, returning the value of that function call. When using|>
it's helpful to remember that the function argument should be on theleft handside of the operator. The value of this operator might not be immediately obvious--after all, why use special operators for function application when parentheses will suffice 🤔--but you'll often see multiple instances of the|>
operator chained together to form a complete expression.
pipeRightEx : Optional Nat
pipeRightEx =
use Nat +
Some 5 |> Optional.filter Nat.isEven |> Optional.map (n -> n + 1)
You might find that there's a greater fit between the semantic order of this expression and the order in which the function calls are applied than in the non|>
version of this expression:
pipeEx : Boolean
pipeEx = isSome (Optional.filter Nat.isEven (Some 5))
a<|
b
<|
b<| : (a ->{𝕖} b) -> a ->{𝕖} b
When using<|
,the function should be on the left hand side of the operator with the function's argument on the right hand side. You can read the<|
operator as "pipe backwards." You might choose to use this operator when the argument to the function in question needs some "pre-processing" which would otherwise involve parentheses.
pipeBackwardsEx : Optional Nat
pipeBackwardsEx =
Optional.filter Nat.isEven <| pipeBackwardsEx.wrap 5
Note that the<|
operator does not change the precedence of the operator function calls. The leftmost sub-expression is still executed first. You can use parentheses to change the grouping.