Open gurustron opened 1 year ago
This is a consequence of https://github.com/fsharp/fslang-suggestions/issues/816 . FSharp equality and comparison badly need to move into the generic era.
This is by design - F# structural equality and comparison builds on IComparable
, not IComparable<T>
If you want to enforce non-structural comparison throughout your code you can do this:
open FSharp.Core.Operators.NonStructuralComparison
open System.Numerics
let inline test<'T when 'T :> INumber<'T>> (x:'T) =
if x > 'T.Zero then x
else 'T.Zero
However this means, for example, you can't use structural equality on F# lists or tuples or arrays.
If you need to mix of structural comparison and non-structural comparison, you can do this:
let inline (>.) x y = FSharp.Core.Operators.NonStructuralComparison.(>) x y
let inline (>=.) x y = FSharp.Core.Operators.NonStructuralComparison.(>=) x y
let inline (<.) x y = FSharp.Core.Operators.NonStructuralComparison.(<) x y
let inline (<=.) x y = FSharp.Core.Operators.NonStructuralComparison.(<=) x y
let inline (=.) x y = FSharp.Core.Operators.NonStructuralComparison.(=) x y
let inline (<>.) x y = FSharp.Core.Operators.NonStructuralComparison.(<>) x y
open System.Numerics
let inline test<'T when 'T :> INumber<'T>> (x:'T) =
if x >. 'T.Zero then x
else 'T.Zero
That is interesting. How does that work? These operators don't work with IComparable<'T>.
open System
open NonStructuralComparison
type T() =
interface IComparable<T> with member _.CompareTo(_:T) = 0
let compared = T() < T() // The type 'T' does not support the operator '<'
This one works on IComparable<'T>
including INumber
.
let inline (>.) (x: 'T) (y: 'T) = (x:> IComparable<'T>).CompareTo(y) > 0
Repro steps
Actual behavior
Compilation error:
Expected behavior
Compiles like C# counterpart:
Known workarounds
Add the constraint:
Related information