Abel
Abel

Reputation: 57159

Type extensions with a generic constraint not raising an error, nor doing what might be expected

Consider the following code snippet using F# 4.0, .NET 4.6:

type X<'T> = Y of 'T

type XS = X<string>
type XI = X<int>

type X<'T when 'T :> string> with
    static member X = 2
    static member take (s: 'T) = s

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module XS =
    let foo = 10
    let create s = XS.Y s
    let test = XI.take 2    // expected only string allowed, XI.take should not exist

I would expect the type extension type X<'T when 'T :> string> with to either be respected (in this case that would mean an error, because string is sealed, or restrict 'T to be string), or to raise a syntax error.

What is more, I can use the following syntax as well, which would be a syntax error in a normal type definition (without with):

type X<'T> when 'T :> string with
    static member X = 2
    static member take (s: 'T) = s

My guess is that the constraint is simply ignored on the extension. Is that by design? Or is it supposed to work and if so, how?

I came to all this when experimenting a bit with type extensions and wondering whether I could create a specific set of methods that only apply to a specific concrete type, or a further restricted concrete type (something that can also be done by inheritance, I know).

Upvotes: 4

Views: 96

Answers (1)

kvb
kvb

Reputation: 55184

I think the compiler should reject your code, but here are a few observations:

  1. Note that the behavior is different if you use an "extrinsic" extension (e.g. by putting the definition and extension in different modules - see Type Extensions) - there, the compiler flags the extension as an error.
  2. If what you want is to have instance extension methods that show up only for certain concrete values of the type parameter, then you can use a C#-style extension method (this is also explained at the link above). However, because C# doesn't support static extension members, there's no way to apply this trick to your scenario.

Upvotes: 3

Related Questions