Description
The C#-way of doing quick pattern matching and value extraction is by declaring member functions of name Deconstruct
, or static extension methods accordingly. A Deconstruct
method has the signature of:
public void Deconstruct(out T1 name1, out T2 name2, ...)
... which actively extracts values from the class instance.
Multiple overloads can be supplied to accommodate different ways of deconstruction.
In F#, we automatically receive pattern matching benefits for DUs and records, but currently the only way to peek into the content of a class instance in a pattern, is to create an active pattern for it. Since active patterns cannot be overloaded, one has to come up with different names for different ways of extraction, which adds extra complexity to the matter.
So I propose that we support this in F#.
A new kind of pattern is then added to classes, which allows a class to be matched against a tuple. When the compiler sees such a pattern, it looks up the class definition and extensions for Deconstruct
methods, and align the tuple signature with the [<Out>] T byref
parameters -- the [<Out>]
and byref
part should be removed. Then further matching of the elements in the tuple may proceed. Type inference rules unify the items.
Note, it's not possible practical to use records (anonymous or not) in this case, because there can be multiple Deconstruct
overloads.
A quick glance of what it may look like:
type MyEventArgs() =
inherits EventArgs()
member val foo: int = 123 with get, set
member x.Deconstruct([<Out>] foo: _ byref) =
foo <- x.foo
// later:
myControl.MyEvent.Subscribe(fun (foo: int) ->
printfn "extracted foo = %d" foo
) |> ignore
Applications Brainstorming
- It would be then very cool to also add support in
FSharp.Data
, so that the provided types can have better pattern matching. - A
ResizeArray<T>
can be then matched as a list! - Allow custom deconstruction on DU/records?
- (Going too far maybe?) if some parameters are not marked as
[<Out>] byref
, it can be used as input parameter, giving it full active pattern matching capabilities
Pros and Cons
The advantages of making this adjustment to F# are:
- More natural pattern matching on classes
- Better interop with C# while not disrupting the F# paradigms
The disadvantages of making this adjustment to F# are:
- Implicit dependency on the name
Deconstruct
[<Out>] name: T byref
seems taboo in F#- (Taken from the C# docs) Multiple Deconstruct methods that have the same number of out parameters or the same number and type of out parameters in a different order can cause confusion
- ...but C# already did this
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
- I have searched both open and closed suggestions on this site and believe this is not a duplicate
- 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.
Please tick all that apply:
- 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