模式匹配和构造函数

时间:2012-04-18 13:20:52

标签: functional-programming pattern-matching ocaml

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

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必须出现在此|的两侧图案

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

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

错误:此模式匹配float 类型的int类型的值          但预计会匹配值

的模式

2 个答案:

答案 0 :(得分:8)

如果您为多个模式提供单一右侧(就像您一样),OCaml要求模式始终与模式变量绑定。

在第一种情况下,

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

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

在第二种情况下,

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

模式与要绑定到变量的值的类型不一致:第一个模式将类型int的值绑定到i,而第二个模式绑定类型{{{ 1}}到float

这两种模式可以一致地绑定到变量的唯一方法是不要绑定任何变量:

i

然后完整的例子变成

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

(但请注意,模式匹配的最后一个部分是多余的,因为前两个模式已经详尽地匹配了您的类型type t = A of int | B of float let f = function | A _ | B _ -> true | _ -> false 的所有值。因此,我们得到:

t

这当然等同于写let f = function | A _ | B _ -> true 。)

答案 1 :(得分:3)

Or模式(|模式)中,您将无法跟踪您所在的构造函数。因此,您需要绑定同一组变量才能工作而无需引用构造函数。

OCaml是强类型的;值i不能同时具有int类型和float类型。

如果类型t有两种以上的情况,您应该写:

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)