Moritz Beutel
Moritz Beutel

Reputation: 1941

F# type matching with ":? Type as name": why do we need a new name?

I was looking at the pattern matching syntax for types in F# described here:

http://msdn.microsoft.com/de-de/library/dd547125.aspx#sectionToggle14

Example from that page (slightly modified):

open System.Windows.Forms

let RegisterControl (control: Control) =
    match control with
    | :? Button as button -> button.Text <- "Registered."
    | :? CheckBox as checkbox -> checkbox.Checked <- false
    | _ -> ()

What I don't understand is why we need to introduce a new name ("button", "checkbox") along with the typecheck. If the match succeeded, the compiler should know that "control" has the desired type and could treat it accordingly in the following expression/statement. In other words, why can't I do this:

open System.Windows.Forms

let RegisterControl (control: Control) =
    match control with
    | :? Button -> control.Text <- "Registered."
    | :? CheckBox -> control.Checked <- false
    | _ -> ()

This would be similar to the "type guard" feature in TypeScript 1.4.

Is there a good reason why F# doesn't do that [yet]? (Note: I'm running VS 2012.)

Upvotes: 1

Views: 96

Answers (2)

scrwtp
scrwtp

Reputation: 13577

This would be trading a consistent model for an inconsistent one.

It's not entirely true that you need to introduce a new name. This works quite well:

match control with
| :? Button -> doButtonyStuff control
| :? CheckBox -> doCheckBoxyStuff control
| _ -> ()

Except of course your control value stays a Control in the match case bodies. You only introduce the name when you want to do a typecheck (C#-style is) and a cast (C#-style as) in your match pattern.

What you suggest could easily be imagined as having an implicit shadowing of control: Control you use in the match with another control: Button after the cast. One problem I see with it is that it has a collateral effect of making the control: Control inaccessible in the match case bodies. That might not be a big deal in your particular example, but if you're checking against interface types, it might become unwieldy.

No pattern matching constructs do such an implicit thing today. Unless you do so yourself, your bindings don't get shadowed. That's good if you ask me. Explicit is better than implicit.

Upvotes: 2

Tomas Petricek
Tomas Petricek

Reputation: 243061

One obvious reason why you need a new name is when the parameter of match is an expression:

match some.Method() with
| :? Button -> // What to do here??

Of course, the language could support of the notations. In that case, there is no technical reason why you could not do this, but I think there is a pretty good logical reason for not doing this.

Every value in F# has a location where it is explicitly declared (when you're using a value, you can always go to definition). The values that would be defined using this simplified :? Type syntax would not really have any declaration

  • You could say that they are declared at the point where the original variable is declared, but that's wrong - because there, it would have different type.

  • Or you could say that they are declared in some "hidden way", but that would introduce a completely new concept to the language.

That said, I can see why the syntax is nice and useful. But it does not seem to fit well with the logic of how variables work in F#.

Upvotes: 4

Related Questions