2016-11-18 3 views
2

OCamlでは、パターンマッチング中にデータコンストラクタの勇気に名前をバインドできますか?実例として、私は以下のOCamlのプログラムがあるとします。OCamlで一致する合計型のバインディング名

type t = A of int * int | B of int * int 

let sum_pair (a, b) = a + b 

let f x = match x with 
    | A (a1, a2) -> sum_pair (a1, a2) 
    | B (_, b) -> b 

let _ = Printf.printf "%d\n" (f (A (1, 2))) 

これはコンパイルが、それは私がsum_pairにそれを渡すためにマッチング後のタプル(a1, a2)を再構築する必要があることを、むしろ迷惑なんです!代わりに、私は

let f x = match x with 
    | A (_ as pair) -> sum_pair pair 
    | B (_, b) -> b 

を書くことができるようにしたいが、これは失敗すると、「エラー:コンストラクタAは2引数(複数可)を想定していますが、1つの引数(複数可)にここで適用されます」これは全体の値ではなく、ペア内にpairをバインドするよう

let f x = match x with 
    | A _ as pair -> sum_pair pair 
    | B (_, b) -> b 

を書くことは、何より良いではありません。 "これは式t型ですが、式はint * int型の式が必要です。"

+0

これはBDFLの発言です:http://caml.inria.fr/pub/ml-archives/caml-list/1997/01/f8f69190c168ae796d3a16ed0e0dfa92.en.html – ivg

+1

また、コメントとして正当な理由で言語があなたに抵抗していることに注意してください。それは実際にあなたに何か間違っていることを伝えようとしています。あなたがそれを適用するたびに、新しいペアを作成する必要があるので、カルト関数を作成する正当な理由はありません。だから、あなたは 'sum_pair'にひどいオーバーヘッドがあります。より良いバージョンは: '| A(x、y) - > sum_pair x y' – ivg

答えて

5

このように型を定義した場合、これを行うことができます:

type t = A of (int * int) | B of (int * int) 

これは、コンストラクタAが実際にはという1つの引数である引数を取ることを意味します。元の定義では、2つのint引数がペアではないので、これを回避する方法はありません。

# type t = A of (int * int) | B of (int * int);; 
type t = A of (int * int) | B of (int * int) 

# let sum_pair (a, b) = a + b 

    let f x = match x with 
    | A p -> sum_pair p 
    | B (_, b) -> b 
    ;; 
val sum_pair : int * int -> int = <fun> 
val f : t -> int = <fun> 

# f (A (5, 7));; 
- : int = 12 

これは、OCaml構文のトリッキーな点です。最近の別の議論があります:'as' Keyword in Pattern Matching Behaving Strangely

+1

一般的に私はOCaml構文を嫌いませんが、これはちょっと醜いです。 OPのコンストラクタは、この回答の構文とまったく同じ構文で使用されますが、タイプは異なります。なぜコンストラクタの関数構文を持つことができないのですか?彼らだけがカレーにすることはできないのですか? – user3240588

+0

関数の構文は '[@@ deriving variants]'を参照してください。 – ivg

関連する問題