F#类型匹配“:?键入名称”:为什么我们需要一个新名称?

时间:2014-11-22 17:43:06

标签: .net f# pattern-matching

我在看这里描述的F#中的类型的模式匹配语法:

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

该页面的示例(略有修改):

open System.Windows.Forms

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

我不明白为什么我们需要引入一个新名称(“按钮”,“复选框”)以及类型检查。如果匹配成功,编译器应该知道“control”具有所需的类型,并且可以在以下表达式/语句中相应地对待它。换句话说,为什么我不能这样做:

open System.Windows.Forms

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

这与"type guard" feature in TypeScript 1.4类似。

为什么F#没有那么做呢? (注意:我正在运行VS 2012。)

2 个答案:

答案 0 :(得分:4)

您需要新名称的一个明显原因是,match的参数是表达式:

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

当然,该语言可以支持这些符号。在这种情况下,没有技术上的原因你不能这样做,但我认为有一个很好的逻辑理由不这样做。

F#中的每个值都有一个显式声明的位置(当你使用一个值时,你总是可以去定义)。使用这种简化的:? Type语法定义的值实际上不会有任何声明

  • 您可以说它们是在声明原始变量的位置声明的,但这是错误的 - 因为它会有不同的类型。

  • 或者你可以说它们是以某种隐藏的方式声明的,但这会为语言引入一个全新的概念。

那说,我可以看到为什么语法很好用。但它似乎不符合F#中变量如何运作的逻辑。

答案 1 :(得分:2)

这将为不一致的模型交易一致的模型。

您需要引入新名称并不完全正确。这非常有效:

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

当然,您的control值在匹配案例正文中保持Control。您只需要在匹配模式中进行类型检查(C#-style is)和强制转换(C#-style as)时引入名称。

你建议的内容很容易被想象为在投射后你在与另一个control: Control的匹配中使用control: Button的隐含阴影。我看到的一个问题是,它具有使匹配案例体中control: Control无法访问的附带效果。在您的特定示例中,这可能不是什么大问题,但如果您正在检查接口类型,则可能会变得难以处理。

今天没有模式匹配结构做这样一个隐含的事情。除非你自己这样做,否则你的绑定不会被遮蔽。如果你问我,这很好。明确比隐含更好。