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<[