When working with Unison code, you might encounter the following operators which are provided by the base
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 functions b -> c
and a -> b
and returns a function from a -> 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 expects Text.size
's argument of Text
and returning the final result of applying the Boolean.not
function.
a >>
b
>>
b>> : (a ->{π} b) -> (b ->{π} c) -> a ->{π} c
>>
, also known as andThen
, is like compose
with the function argument order reversed. It takes in two functions a->b
and b->c
and returns a function from a->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 the left hand side 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.