F# RFC FS-1068 - Open static classes
The design suggestion Open static classes has been marked "approved in principle". This RFC covers the detailed proposal for this suggestion.
Add support for opening static classes, e.g.
open System.Math. For example
> open System.Math;; > Min(1.0, 2.0);; val it : float = 1.0 > Min(2.0, 1.0);; val it : float = 1.0 > open System.Math;; > Min(2.0, 1.0);; val it : float = 1.0
This greatly increases the expressivity of F# DSLs by allowing method-API facilities such as named arguments, optional arguments and type-directed overloading to be used in the DSL design.
Additionally, important C# DSL APIs are starting to appear that effectively require this.
- In .NET "static" classes are abstract and sealed, containing only static members.
- In F# these are currently declared through
[<AbstractClass; Sealed>] type C = static member Pi = 3.14 open C Pi
There is a question as to whether we add
static type C =...
The RFC will explain the pros and cons of this feature (and the potential for its abuse).
The implementation is not large but intrudes a little on name resolution and we should take care to assess potential ramifications of those changes
The design has an interaction with type providers: type providers can provide static classes, hence this would allow type providers to provide "unqualified" names. This is no doubt useful for some projections where the natural thing is unqualified, e.g. the "R" type provider always required
The design has an interaction with the F#-only feature "static" extension members, e.g. this works:
type System.Math with static member Pi = 3.1415 open System.Math Pi
This feature should only be used very very carefully.
- Code using this feature may be substantially less clear and harder to understand
- If multiple APIs are
open'd with conflicting method sets then severe usability problems will occur.
- Adding methods to static classes can cause breaking changes or source code incompatibilities in client code using this feature.
The main alternative is "don't do this"
This is a non-breaking change.
- Resolve how static classes are defined in F#
- Respect and test for RequireQualifiedNameAttribute(true) on a static class, that prevents it being opened, or at least gives a warning, as for F# modules.