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はこの両側で発生する必要があります| パターン

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

また

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

エラー:このパターンはfloatタイプのint型の値と一致します が、値と一致するパターンが予期されていました

4

2 に答える 2

8

(あなたがそうするように)複数のパターンに単一の右側を提供する場合、OCamlはパターンが一貫してパターン変数にバインドすることを要求します。

最初の状況では、

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

パターンは、バインドする変数に同意しません。最初のパターンはにバインドしi、2番目のパターンはにバインドしfます。

2番目の状況では、

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

パターンは、変数にバインドする値のタイプに同意しません。最初のパターンはタイプの値をにバインドしinti2番目のパターンはタイプの値をにバインドfloatしますi

これらの2つのパターンが一貫して変数にバインドできる唯一の方法は、変数にまったくバインドしないことです。

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

完全な例は次のようになります

type t = A of int | B of float

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

(But note that the last arm of the pattern match is superfluous as the first two pattern already exhaustively match all values of your type t. Hence, we get:

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

This of course is equivalent to writing let f _ = true.)

于 2012-04-18T13:41:59.837 に答える
4

Orパターン(パターン)では|、どのコンストラクターを使用しているかがわかりません。したがって、コンストラクターを参照せずに機能するには、同じ変数のセットをバインドする必要があります。

そしてOCamlは強く型付けされています。値にタイプとタイプiの両方を含めることはできません。intfloat

タイプtに3つ以上のケースがある場合は、次のように記述します。

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 に答える