I have a type for logging levels:
type LoggingLevel =
| Trace
| Debug
| Info
I would like to say that some logging levels are higher than others. For example, Trace is higher than Info.
So I implemented IComparable like this:
[<StructuralEqualityAttribute>]
[<CustomComparisonAttribute>]
type LoggingLevel =
| Trace
| Debug
| Info
interface IComparable<LoggingLevel> with
override this.CompareTo other =
let score x =
match x with
| Trace -> 0
| Debug -> 1
| Info -> 2
(score this) - (score other)
But when I try to use it, I get an error:
if a >= b
then
// ...
The type 'LoggingLevel' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
How have I gone wrong here?
I managed to get it working, but now the type definition is so verbose! There must be a better way...
[<CustomEquality>]
[<CustomComparisonAttribute>]
type LoggingLevel =
| Trace
| Debug
| Info
override this.Equals (obj) =
match obj with
| :? LoggingLevel as other ->
match (this, other) with
| (Trace, Trace) -> true
| (Debug, Debug) -> true
| (Info, Info) -> true
| _ -> false
| _ -> false
override this.GetHashCode () =
match this with
| Trace -> 0
| Debug -> 1
| Info -> 2
interface IComparable<LoggingLevel> with
member this.CompareTo (other : LoggingLevel) =
let score x =
match x with
| Trace -> 0
| Debug -> 1
| Info -> 2
(score this) - (score other)
interface IComparable with
override this.CompareTo other =
(this :> IComparable<LoggingLevel>).CompareTo (other :?> LoggingLevel)
I think you're comparison implementation is off here based on the typing. The following compiles for me:
[<CustomComparison>]
[<StructuralEquality>]
type LoggingLevel =
| Trace
| Debug
| Info
interface System.IComparable with
member this.CompareTo other =
0
// replace 0 with your comparison logic here
let a = Trace
let b = Debug
if Trace > Debug then printfn "here"
Note that other in this case will be of type obj and you'll need to box accordingly. Made all the trickier by the fact that all cases here are empty (i.e. lacking type)
I would be curious to see a more complete example, of you attempting to use this logic. I suspect a match expression might be better and allow you to remove this custom comparison.
That said, without knowing your exact use case, wouldn't something like this be more functional (and perhaps) simpler?
type LoggingLevel = Trace | Debug | Info
module Logger =
let doSomeLogging logLevel =
match logLevel with
| Trace -> "trace"
| Debug -> "debug"
| Info -> "info"
let result = Logger.doSomeLogging Trace
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With