marp | title | theme | progress | paginate |
---|---|---|---|---|
true |
F#7 and next |
uncover |
true |
true |
and what's next
(runtime SRTPs, sort of)
Declaration
type IAddition<'T when 'T :> IAddition<'T>> =
static abstract op_Addition: 'T * 'T -> 'T
Implementation
type Number<'T when IAddition<'T>>(value: 'T) =
member _.Value with get() = value
interface IAddition<Number<'T>> with
static member op_Addition(a, b) = Number(a.Value + b.Value)
Consuming
let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = 'T.op_Addition(x,y)
// or using the operator form
let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = x + y
Generic math examples
open System.Numerics
let sum<'T when INumber<'T>>(values: seq<'T>) =
let mutable result = 'T.Zero
for value in values do
result <- result + value
result
Example of a function with static trait
let inline average< ^T
when ^T: (static member (+): ^T * ^T -> ^T)
and ^T: (static member DivideByInt : ^T * int -> ^T)
and ^T: (static member Zero : ^T)>
(xs: ^T array) =
let mutable sum : ^T = (^T : (static member Zero: ^T) ())
for x in xs do
sum <- (^T : (static member op_Addition: ^T * ^T -> ^T) (sum, x))
(^T : (static member DivideByInt: ^T * int -> ^T) (sum, xs.Length))
Simplified call syntax and unified constraints
let inline average<'T
when 'T: (static member (+): 'T * 'T -> 'T)
and 'T: (static member DivideByInt : 'T * int -> 'T)
and 'T: (static member Zero : 'T)>
(xs: 'T array) =
let mutable sum = 'T.Zero
for x in xs do
sum <- sum + x
'T.DivideByInt(sum, xs.Length)
Constraints/traits grouping
type AverageOps<'T when 'T: (static member (+): 'T * 'T -> 'T)
and 'T: (static member DivideByInt : 'T*int -> 'T)
and 'T: (static member Zero : 'T)> = 'T
let inline average<'T when AverageOps<'T>>(xs: 'T array) =
let mutable sum = 'T.Zero
for x in xs do
sum <- sum + x
'T.DivideByInt(sum, xs.Length)
also works with instance members
type Length<'T when 'T: (member Length: int)> = 'T
let inline len<'T when Length<'T>>(x: 'T) =
x.Length
Other F# 7 features
- Required and init-only properties checking.
- Reference assemblies support (still experimental).
- Better self-contained deployments and NAOT support (reflection-free compilation).
- ARM64 platform-specific compiler, and ARM64 target support in F# compiler.
- Parallel type- and project-checking support (experimental, enabled via VS flag or by tooling authors).
- General .NET7 improvements F# benefits from - https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/
What's next (F# 8)
- Better nullable interop (exhaustiveness, respecting and emitting .NET metadata, ? postfixed types support (under consideration))
- Extension members support in SRTPs.
type Option<'T> with member _.Bind(...) = ... type Result<'T> with member _.Bind(...) = ... let inline bind<'M when 'M: (member Bind: ... -> ...)> f (m: 'M) = m.Bind(f)
- Scoped refs and better escape analysis
Continued
- Anonymous type-tagged unions support
let intOrString : (int|string) = if true then 1 else "Hello" let prettyPrint (x: (int8|int16|int64|string)) = match x with | :? int8 -> prettyPrintInt8 x | :? int16 -> prettyPrintInt16 x | :? int64 -> prettyPrintInt64 x | :? string as y -> prettyPrintString y
- Tooling performance improvements - parallel type-checking, incremental compilation.
- Optional
fun
keyword for lambdas. - Raw interpolated strings (aka double-dollar or
$$
).