Operators
Definition
Function whose name is a set of symbols
Unary operator:
let (~symbols) = ...
Binary operator:
let (symbols) = ...
Symbols = combination of
% & * + - . / < = > ? @ ^ | ! $
2 ways of using operators:
As an operator:
1 + 2
without the
()
prefix position if unary
-1
.infix position id binary
1 + 2
As a function:
(+) 1 2
with the
()
Standard operators
Also defined in FSharp.Core
.
Arithmetic operators:
+
,-
...Pipeline operators
Composition operators
Piping operators
Binary operators, placed between a simple value and a function
Apply the value to the function = Pass value as argument
Avoid parentheses otherwise required for precedence reason
There are several pipes
Pipe right
|>
: the usual pipePipe left
<|
a.k.a. reversed pipePipe right 2
||>
Etc.
Pipe right |>
|>
Reverse the order between function and value: val |> fn
ā” fn val
Natural "subject-verb" order, as a method call of an object (
obj.M(x)
)Pipeline: chain function calls, without intermediate variable
Help the type inference - example:
Pipe left <|
<|
fn <| expression
ā” fn (expression)
ā Usage a little less common than
|>
ā Minor advantage: avoids parentheses
ā Major disadvantage: reads from right to left ā Reverses natural English reading direction and execution order
Quid of such expression: x |> fn <| y
ā
x |> fn <| y
āExecuted from left to right: (x |> fn) <| y
ā” (fn x) <| y
ā” fn x y
Goal: use
fn
as infixCons: difficult to read because of double reading direction ā
š Tip: TO AVOID
Pipe right 2 ||>
||>
(x, y) ||> fn
ā” fn x y
To pass 2 arguments at once, in the form of a tuple
Used infrequently, but useful with
fold
to pass the initial value (seed
) and the list before defining thefolder
function and help the type inference for a lambdafolder
.
āļø This operator corresponds to the notion of "uncurrying", i.e. being able to call a curried f
function by passing it these 2 parameters in the form of a tuple:
Compose >>
>>
Binary operators, placed between two functions ā The result of the 1st function is used as an argument for the 2nd function
f >> g
ā” fun x -> g (f x)
ā” fun x -> x |> f |> g
The out/in types must match:
f: 'T -> 'U
andg: 'U -> 'V
ā'U
āSignature of the final function:
'T -> 'V
.
Reversed Compose <<
<<
Rarely used, except to restore a natural reading order.
Example with not
(which replaces the !
in CāÆ):
Pipe |>
or Compose >>
?
|>
or Compose >>
?Compose
let h = f >> g
Functions
Pipe
let result = value |> f
Values
Point-free style
A.k.a Tacit programming
Writing functions without mentioning the parameters (referred here as "points"), just by using function composition (1) or partial application (2).
Pros/Cons āļø
ā
Pros
Concise style
At function/operation level, by abstracting the parameters
ā Cons
Loses the name of the parameter now implicit in the signature ā Unimportant if the function remains understandable:
When the parameters name is not significant (e.g.
x
)When the combination of parameters type + function name is unambiguous
For private usage - Not recommended for a public API
Limit š
Works poorly with generic functions:
Custom operators
2 possibilities:
Operator overload
Creation of a new operator
Operator overload
Usually concerns a specific type ā Overload defined within the associated type (as in CāÆ)
Creation of a new operator
Definition rather in a module or associated type
Usual use-case: alias for existing function, used as infix
Symbols allowed in an operator
Unary operator "tilde "
ā ~
followed by +
, -
, +.
, -.
, %
, %%
, &
, &&
Unary operator "snake "
ā Several ~
, e.g. ~~~~
Unary operator "bang "
ā !
followed by a combination of !
, %
, &
, *
, +
, .
, /
, <
, =
, >
, @
, ^
, |
, ~
, ?
ā Except !=
(!=) which is binary
Binary operator
ā Any combination of !
, %
, &
, *
, +
, .
, /
, <
, =
, >
, @
, ^
, |
, ~
, ?
ā which does not match a unary operator
Usage symbols
All operators are used as is
ā Except the unary operator "tilde": used without the initial ~
.
Unaire tilde
let (~&&) x = ā¦
&&x
Unaire snake
let (~~~) x = ā¦
~~~x
Unaire bang
let (!!!) x = ā¦
!!!x
Binary
let (<Ė>) x y = ā¦
x <Ė> y
ā To define an operator beginning or ending with a *
, you must put a space between (
and *
as well as between *
and )
to distinguish from a block of F⯠comments (* *)
.
ā let ( *+ ) x y = x * y + y
ā
Operator or function?
Infix operator vs function
š Pros :
Respects the natural reading order (left ā right)
avoids parentheses ā
1 + 2 * 3
vsmultiply (add 1 2) 3
ā
1 + 2 * 3
vsmultiply (add 1 2) 3
ā ļø Cons :
A "folkloric" operator (e.g.
@!
) will be less comprehensible than a function whose name uses the domain language.
Using an operator as a function
š” You can use the partial application of a binary operator :
Examples:
Instead of a lambda: ā
(+) 1
ā”fun x -> x + 1
To define a new function : ā
let isPositive = (<) 0
ā”let isPositive x = 0 < x
ā”x >= 0
\
Last updated
Was this helpful?