diff --git a/docs/release-notes/.FSharp.Core/9.0.100.md b/docs/release-notes/.FSharp.Core/9.0.100.md index 503a6c17d85..0d0e82c932d 100644 --- a/docs/release-notes/.FSharp.Core/9.0.100.md +++ b/docs/release-notes/.FSharp.Core/9.0.100.md @@ -5,6 +5,7 @@ * Enable C# collection expression support for F# lists & sets. ([Language suggestion #1355](https://github.com/fsharp/fslang-suggestions/issues/1355), [RFC FS-1145 (PR#776)](https://github.com/fsharp/fslang-design/pull/776), [PR #17359](https://github.com/dotnet/fsharp/pull/17359)) * Add module functions for converting between `'T option` and `'T voption`. ([PR #17436](https://github.com/dotnet/fsharp/pull/17436)) +* Add `Units` static type which aids in the addition, removal, and conversion of units of measure for primitive types and common collections of primitive types. ([Language Suggestion #892](https://github.com/fsharp/fslang-suggestions/issues/892)) ([RFC FS-1148 #784](https://github.com/fsharp/fslang-design/pull/784)) ([PR #17581](https://github.com/dotnet/fsharp/pull/17518)) ### Changed * Change compiler default setting realsig+ when building assemblies ([Issue #17384](https://github.com/dotnet/fsharp/issues/17384), [PR #17378](https://github.com/dotnet/fsharp/pull/17385)) diff --git a/src/FSharp.Core/FSharp.Core.fsproj b/src/FSharp.Core/FSharp.Core.fsproj index 418f8a57c52..ebcd16da879 100644 --- a/src/FSharp.Core/FSharp.Core.fsproj +++ b/src/FSharp.Core/FSharp.Core.fsproj @@ -277,6 +277,9 @@ Queries/Query.fs + + Units/Units.fs + Units/SI.fs diff --git a/src/FSharp.Core/Units.fs b/src/FSharp.Core/Units.fs new file mode 100644 index 00000000000..1b826493466 --- /dev/null +++ b/src/FSharp.Core/Units.fs @@ -0,0 +1,763 @@ +namespace Microsoft.FSharp.Core + +open Microsoft.FSharp.Collections + +[] +module private UnitsHelpers = + let inline retype (x: 'T) : 'U = + (# "" x: 'U #) + +type Units = + static member inline Add<[] 'Measure>(input: byte) : byte<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: float) : float<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: int16) : int16<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: int) : int<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: int64) : int64<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: sbyte) : sbyte<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: nativeint) : nativeint<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: uint16) : uint16<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: uint) : uint<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: uint64) : uint64<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: decimal) : decimal<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: float32) : float32<'Measure> = + retype input + + static member inline Add<[] 'Measure>(input: unativeint) : unativeint<'Measure> = + retype input + + static member inline Remove<[] 'Measure>(input: byte<'Measure>) : byte = + retype input + + static member inline Remove<[] 'Measure>(input: float<'Measure>) : float = + retype input + + static member inline Remove<[] 'Measure>(input: int16<'Measure>) : int16 = + retype input + + static member inline Remove<[] 'Measure>(input: int<'Measure>) : int = + retype input + + static member inline Remove<[] 'Measure>(input: int64<'Measure>) : int64 = + retype input + + static member inline Remove<[] 'Measure>(input: sbyte<'Measure>) : sbyte = + retype input + + static member inline Remove<[] 'Measure>(input: nativeint<'Measure>) : nativeint = + retype input + + static member inline Remove<[] 'Measure>(input: uint16<'Measure>) : uint16 = + retype input + + static member inline Remove<[] 'Measure>(input: uint<'Measure>) : uint = + retype input + + static member inline Remove<[] 'Measure>(input: uint64<'Measure>) : uint64 = + retype input + + static member inline Remove<[] 'Measure>(input: decimal<'Measure>) : decimal = + retype input + + static member inline Remove<[] 'Measure>(input: float32<'Measure>) : float32 = + retype input + + static member inline Remove<[] 'Measure>(input: unativeint<'Measure>) : unativeint = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: byte<'MeasureIn>) + : byte<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: float<'MeasureIn>) + : float<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: int16<'MeasureIn>) + : int16<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: int<'MeasureIn>) + : int<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: int64<'MeasureIn>) + : int64<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: sbyte<'MeasureIn>) + : sbyte<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: nativeint<'MeasureIn>) + : nativeint<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: uint16<'MeasureIn>) + : uint16<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: uint<'MeasureIn>) + : uint<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: uint64<'MeasureIn>) + : uint64<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: decimal<'MeasureIn>) + : decimal<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: float32<'MeasureIn>) + : float32<'MeasureOut> = + retype input + + static member inline Cast<[] 'MeasureIn, [] 'MeasureOut> + (input: unativeint<'MeasureIn>) + : unativeint<'MeasureOut> = + retype input + + static member inline AddArray<[] 'Measure>(input: byte[]) : byte<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: float[]) : float<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: int16[]) : int16<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: int[]) : int<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: int64[]) : int64<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: sbyte[]) : sbyte<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: nativeint[]) : nativeint<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: uint16[]) : uint16<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: uint[]) : uint<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: uint64[]) : uint64<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: decimal[]) : decimal<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: float32[]) : float32<'Measure>[] = + retype input + + static member inline AddArray<[] 'Measure>(input: unativeint[]) : unativeint<'Measure>[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: byte<'Measure>[]) : byte[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: float<'Measure>[]) : float[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: int16<'Measure>[]) : int16[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: int<'Measure>[]) : int[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: int64<'Measure>[]) : int64[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: sbyte<'Measure>[]) : sbyte[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: nativeint<'Measure>[]) : nativeint[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: uint16<'Measure>[]) : uint16[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: uint<'Measure>[]) : uint[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: uint64<'Measure>[]) : uint64[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: decimal<'Measure>[]) : decimal[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: float32<'Measure>[]) : float32[] = + retype input + + static member inline RemoveArray<[] 'Measure>(input: unativeint<'Measure>[]) : unativeint[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: byte<'MeasureIn>[]) + : byte<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: float<'MeasureIn>[]) + : float<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: int16<'MeasureIn>[]) + : int16<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: int<'MeasureIn>[]) + : int<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: int64<'MeasureIn>[]) + : int64<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: sbyte<'MeasureIn>[]) + : sbyte<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: uint16<'MeasureIn>[]) + : uint16<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: uint<'MeasureIn>[]) + : uint<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: uint64<'MeasureIn>[]) + : uint64<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: decimal<'MeasureIn>[]) + : decimal<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: float32<'MeasureIn>[]) + : float32<'MeasureOut>[] = + retype input + + static member inline CastArray<[] 'MeasureIn, [] 'MeasureOut> + (input: unativeint<'MeasureIn>[]) + : unativeint<'MeasureOut>[] = + retype input + + static member inline AddResizeArray<[] 'Measure>(input: ResizeArray) : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure>(input: ResizeArray) : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure>(input: ResizeArray) : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline AddResizeArray<[] 'Measure> + (input: ResizeArray) + : ResizeArray> = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure>(input: ResizeArray>) : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline RemoveResizeArray<[] 'Measure> + (input: ResizeArray>) + : ResizeArray = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline CastResizeArray<[] 'MeasureIn, [] 'MeasureOut> + (input: ResizeArray>) + : ResizeArray> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline AddList<[] 'Measure>(input: list) : list> = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline RemoveList<[] 'Measure>(input: list>) : list = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline CastList<[] 'MeasureIn, [] 'MeasureOut> + (input: list>) + : list> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline AddSeq<[] 'Measure>(input: seq) : seq> = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline RemoveSeq<[] 'Measure>(input: seq>) : seq = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input + + static member inline CastSeq<[] 'MeasureIn, [] 'MeasureOut> + (input: seq>) + : seq> = + retype input