1

为什么我在编写这种模式匹配时会出错:

type t = A of int | B of float

let f = function
        | (A i | B f) -> true
        | _ -> false

或者

let f = function
        | A i | B f -> true
        | _ -> false

错误:变量 f 必须出现在 this 的两边 | 图案

let f = function
        | (A i | B i) -> true
        | _ -> false

或者

let f = function
        | A i | B i -> true
        | _ -> false

错误:此模式匹配浮点类型的整数类型的值, 但预期的模式与值匹配

4

2 回答 2

8

如果您为多个模式提供单个右侧(如您所做的那样),OCaml 要求模式始终绑定到模式变量。

在第一种情况下,

match ... with
  | A i | B f -> ...
  ...

模式在它们绑定到的变量上不一致:第一个模式绑定到i,而第二个绑定到f.

在第二种情况下,

match ... with
  | A i | B i -> ...
  ...

模式不同意绑定到其变量的值的类型:第一个模式将类型的值绑定inti,而第二个模式将类型的值绑定floati

这两种模式可以始终绑定到变量的唯一方法是根本不绑定到任何变量:

match ... with
  | A _ | B _ -> ...
  ...

完整的例子就变成了

type t = A of int | B of float

let f = function
  | A _ | B _ -> true
  | _ -> false

(但请注意,模式匹配的最后一个分支是多余的,因为前两个模式已经完全匹配您的 type 的所有值t。因此,我们得到:

let f = function
  | A _ | B _ -> true

这当然等同于写作let f _ = true。)

于 2012-04-18T13:41:59.837 回答
4

Or模式(|pattern)中,你会忘记你所在的构造函数。因此,你需要绑定同一组变量才能工作,而不需要引用构造函数。

OCaml 是强类型的;一个值i不能同时具有 typeint和 type float

如果 typet有两种以上的情况,你应该写:

let f = function
        | A _ | B _ -> true
        | _ -> false

否则:

let f = function
        | A _ | B _ -> true

就足够了,因为模式匹配已经很详尽了。

我同意这种Or模式非常严格,但有时当你的函数中有对称情况时它会很有帮助:

type num = 
    | Int of int
    | Float of float

let add s1 s2 = 
    match s1, s2 with
    | Int i1, Int i2 -> Int (i1 + i2)
    | Int i, Float f | Float f, Int i -> Float (float i +. f)
    | Float f1, Float f2 -> Float (f1 +. f2)
于 2012-04-18T13:40:06.223 回答