模式匹配语法中的歧义

时间:2016-06-22 15:06:56

标签: f#

我今天在F#模式匹配语法中遇到了一个奇怪的问题,这可能导致穷举检查中的明显失败。

type Thing =
    | This
    | That
    | Other

let useThing =
    function
    | This -> "A"
    | That -> "A"
    | That -> "B" // compiler complains
    | Other -> "B"

在上面的场景中,编译器有用地告诉我第二条规则永远不会匹配。但是,如果我试图使代码更紧凑并编写

let useThing =
    function
    | This | That -> "A"
    | That | Other -> "B"    

我没有得到编译器的任何帮助。我认为原因是| This | That ->. "A"不是| This -> "A" | That -> "A"的快捷方式,即使它看起来非常像(并且我已经看过很多代码示例)这样对待它)。相反,根据我的发现,管道符号既可用于分隔单个模式,也可用作OR模式。

对于大多数DU而言,这不是一个大问题,但是在将具有大量案例的DU映射到具有少量案例的另一个DU时遇到了问题。我尝试使用快捷语法导致了一个错误。

所以我的问题是:

  1. 我的解释是否正确?
  2. 除了在单独的一行上列出每个模式之外,还有其他解决方法吗?

1 个答案:

答案 0 :(得分:8)

您的解释是正确的。

通过省略第一个This和第二个That的操作,您正在创建一个OR模式,如Pattern Matching (F#)

中所述

对我而言,这也有点令人困惑,因为逻辑'或'是||在F#中。 虽然在格式化中很容易看到第一个栏为new alternative,第二栏为or,但在

中显得不那么明显
let useThing =
    function
    | This
    | That -> "A"
    | That
    | Other -> "B"

然而,编译器可以判断整个模式是否无用,但它无法简化模式。 That | Other具有有效匹配,因此编译器不会考虑冗余 您可以想到更多涉及的模式,如果可以省略部件或如何简化它们,那么根本不清楚。