I still cannot understand why I would use the keyword inline
for a function.
What does it give me that I don't already have?
let inline (|Positive|Neutral|Negative|) x =
match sign x with
| 1 -> Positive
| -1 -> Negative
| _ -> Neutral
In this case, it may be easier to understand what inline
gives you if you try to remove the keyword:
let (|Positive|Neutral|Negative|) x =
match sign x with
| 1 -> Positive
| -1 -> Negative
| _ -> Neutral
This active pattern has the type float -> Choice<unit,unit,unit>
. Notice that the compiler has inferred that it only works for float
input.
The consequences of this may be most apparent if we also define a function that uses this pattern, e.g. one that determines if a number is a natural number:
let isNatural = function
| Positive -> true
| _ -> false
This function has the type float -> bool
, which means that you can use it only with float
input:
> isNatural 1.;;
val it : bool = true
> isNatural 1;;
> isNatural 1;;
----------^
stdin(4,11): error FS0001: This expression was expected to have type
float
but here has type
int
What if you want to be able to determine that both float
, int
, int64
, etcetera, are natural numbers? Should you duplicate these functions for all input types?
You don't have to. You can inline
the functions:
let inline (|Positive|Neutral|Negative|) x =
match sign x with
| 1 -> Positive
| -1 -> Negative
| _ -> Neutral
let inline isNatural x =
match x with
| Positive -> true
| _ -> false
Because of the inline
keyword, the compiler keeps the type of the functions generic:
>
val inline ( |Positive|Neutral|Negative| ) :
x: ^a -> Choice<unit,unit,unit> when ^a : (member get_Sign : ^a -> int)
val inline isNatural : x: ^a -> bool when ^a : (member get_Sign : ^a -> int)
This means that you can use any type for input, as long as there exists a function get_Sign
that takes that type as input, and returns int
.
You can now call the functions with both float
, int
, and other numeric types:
> isNatural 1.;;
val it : bool = true
> isNatural 1;;
val it : bool = true