LSM07
LSM07

Reputation: 817

Restricting Operator Use to a single Class

Q: In F#, Is it absolutely necessary to declare operators for types within the type declaration itself?

To enforce some extra safety with regards to certain types, I wanted to define a type but only allow operations on that type from a specific class. I have the following code:

/// Tracks identity of an Event
type EventID = EventID of int

let defaultEventID = EventID 0

/// Singleton to generate IDs for Events
type EventIDManager private () =    
    let mutable currentID = defaultEventID
    static let instance = EventIDManager()
    static member Instance = instance

    /// Operator definition in question
    static member inline private (+.) (EventID(a), EventID(b)) = EventID(a + b)

    /// Simply increments IDs for now
    member private __.advanceID () =
        currentID <- currentID +. (EventID 1) /// Compiler warning here

    member this.generateID () =
        let cur = currentID
        this.advanceID ()
        ///return ID
        cur

    member __.getCurrentID () = currentID

Instead of defining the +. operator in the EventID type itself, I moved it to the EventIDManager. But in the advanceID() method, the compiler gives the following warning:

The type 'EventID' does not support the operator '+.'

Even if I implement the addition in the following way, I still get the same warning:

static member inline private (+.) (e1:EventID) (e2:EventID) =
    match e1, e2 with EventID a, EventID b -> EventID(a + b)

If the operator declaration is moved to the type definition, the problem disappears, but I was curious to see if I could keep the operator definition within the EventIDManager class. Is this possible?

Upvotes: 0

Views: 70

Answers (1)

Nathan Wilson
Nathan Wilson

Reputation: 639

Static members in F# typically need to have the class name out front in order to see it. What I would do (especially since you just want a private operator), is write it as a let binding. So above all your members, just have

let (+.) (EventID a) (EventID b) = EventID(a + b)

and you should be able to use it from the EventIDManager class and nowhere else.

Upvotes: 1

Related Questions