I'm a beginner in F# and i don't understand what are and how to use interfaces. I'm looking at the example found in Expert F# 3.0 page 219
/// A type abbreviation indicating we're using integers for unique stamps
/// on objects
type stamp = int
/// A structural type containing a function that can't be compared for equality
[<CustomEquality; CustomComparison>]
type MyThing =
{Stamp : stamp;
Behaviour : (int -> int)}
override x.Equals(yobj) =
match yobj with
| :? MyThing as y -> (x.Stamp = y.Stamp)
| _ -> false
override x.GetHashCode() = hash x.Stamp
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? MyThing as y -> compare x.Stamp y.Stamp
| _ -> invalidArg "yobj" "cannot compare values of different types"
I'm trying to "copy" this example and would like to create a type called antiint
which would be simply integers, but with the comparer being the opposite of the normal comparison.
let anticompare x y = 0 - compare x y
So i wrote this in my source file:
[<CustomEquality; CustomComparison>]
type antiint =
int
override x.Equals(yobj) =
match yobj with
| :? antiint as y -> (x = y)
| _ -> false
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? antiint as y -> anticompare x y
| _ -> invalidArg "yobj" "cannot compare values of different types"
but it doesn't work... the compiler is underlying in red override complaining "Unexpected keyword 'override' in type definition. Expected '|' or other token".
PS. I wanted to create this type because I want to use the type PriorityQueue to extract max instead of extracting min
As already mentioned in the comments, if you define antiint
as a type abbreviation (also known as type alias), you cannot override its members - or change anything about the type.
The best approach is probably to define it as a value type (struct) that is a thin wrapper over int
. Something like this:
[<Struct; CustomEquality; CustomComparison>]
type antiint(value:int) =
member x.Value = value
override x.Equals(yobj) =
match yobj with
| :? antiint as y -> (x = y)
| _ -> false
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? antiint as y -> anticompare x y
| _ -> invalidArg "yobj" "cannot compare values of different types"
This will be compiled as a value type, so there should be minimal performance overhead. The unfortunate thing is that you won't be able to use standard numerical operators on the above type, so you can either write computations using the Value
property or add operators as discussed in the already referenced blog post I wrote.