Is there a way of constraining a generic type to be a member of a set of types?

Viewed 44

I have the following record

type RecordPath<'a,'b> = {
    Get: 'a -> 'b
    Path:string
}

I want to constrain 'b to be a member of the set of types that can naturally be represented in a relational database column (int; string; DateTime; etc).

I could use a class instead of a record with a private constructor and some static creator methods that only cater for the types I care about. But I was wondering if there is a way to do this with a record.

I also considered extending the types I want to allow with something like this

type String with static member CanBeUsedInRecordPath = true

And then use SRTPs for all functions that operate on a RecordPath, but then it is technically possible (although unlikely) for someone to decide to extend some type I don't want to support with that extension method.

So is a class with a private constructor the only way to do this in F#?

1 Answers

The following seems to satisfy my requirements.

module RecordPath =
    type RecordPath<'a, 'b> = private {
        Get: 'a -> 'b
        Path:string
    }
    with 
        static member Create (f: 'a -> string) = {Get = f; Path = "not important for this demo"}
        static member Create (f: 'a -> int) = {Get = f; Path = "not important for this demo"}
        static member Create (f: 'a -> DateTime) = {Get = f; Path = "not important for this demo"}

I'll wait a bit before accepting this as the answer in case someone comes up with a better way.

Related