fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Proposal: Allow 'T shorthand for dummy type values in SRTP constraints

Open RealmPlume opened this issue 3 months ago • 1 comments

Description

When using SRTP (statically resolved type parameters) in F#, developers often need to pass a dummy value whose only purpose is to fix a type parameter that otherwise wouldn’t be inferred.

Today this requires the verbose (_: 'T) pattern, e.g.:

let inline foo (_: ^g) x y =
    ((^g or ^x or ^y) : (static member Foo : ^x * ^y -> unit) (x, y))

I propose allowing 'g shorthand for such dummy-value parameters:

let inline foo 'g x y =
    ((^g or ^x or ^y) : (static member Foo : ^x * ^y -> unit) (x, y))

This removes visual clutter while preserving semantics.

Motivation / Real-world example

The dummy-value pattern is necessary whenever the SRTP type does not appear in any of the value parameter types. A common case is when static members are grouped on a provider type, and this provider type itself does not occur in the function’s signature.

type Provider = 
    static member Foo(x:int, y:int) = printfn "int add: %d + %d" x y
    static member Foo(x:float, y:float) = printfn "float add: %f + %f" x y

let inline foo (_: ^provider) (x: ^x) (y: ^y) =
    ((^provider or ^x or ^y) : (static member Foo : ^x * ^y -> unit) (x, y))

foo (Unchecked.defaultof<Provider>) 1 2 
foo (Unchecked.defaultof<Provider>) 1.0 2.0

Here ^provider is required to resolve the correct static overload, but it cannot be inferred from x or y. The dummy parameter exists solely to fix the type.

With the proposed shorthand, the declaration becomes:

let inline foo 'provider x y =
    ((^provider or ^x or ^y) : (static member Foo : ^x * ^y -> unit) (x, y))

Pros

  • Removes syntactic noise ((_: 'T)) in SRTP-heavy code.
  • Makes intent clearer: 'provider is a type marker, not a real value.
  • Improves readability of provider/tag-dispatch patterns.

Cons / Considerations

  • Requires parser/grammar support for 'T in value-parameter position.
  • Type checker changes needed to interpret 'T as a dummy value parameter.
  • Needs careful design to avoid ambiguity with existing syntax.

Alternatives

  • Keep the current (_: 'T) pattern (status quo).
  • Official phantom type for SRTP (proposed): F# could provide a dedicated phantom type for this purpose, instead of introducing new syntax. This phantom type would act as a special SRTP carrier. It would be allowed in function parameter patterns with type arguments, e.g.:
    let foo Phan<'g> x y =
          ((^g or ^x or ^y) : (static member Foo : ^x * ^y -> unit) (x, y))

    do foo Phan<Provider> x y
  • The main advantage is that you no longer need to supply a dummy runtime value (Unchecked.defaultof<_>), while using a uniform and clear model for SRTP resolution.

Checklist

  • [x] This is not a question (e.g. like one you might ask on StackOverflow) and I have searched StackOverflow for discussions of this issue

  • [x] This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to the compiler and tooling repository

  • [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it

  • [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate

  • [x] This is not a breaking change to the F# language design

  • [ ] I or my company would be willing to help implement and/or test this

RealmPlume avatar Sep 19 '25 09:09 RealmPlume