2016-11-18 59 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 

但這種失敗「錯誤:構造函數預計2參數(S),但在這裏應用於1個參數(S)。」寫

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

是再好不過了,因爲這結合pair整個值,而不是在一對。 (這也無法編譯,就像你所期望的:「這個表達類型噸,但預計類型爲int * INT的表達。」)

+0

這就是BDFL所說的:http://caml.inria.fr/pub/ml-archives/caml-list/1997/01/f8f69190c168ae796d3a16ed0e0dfa92.en.html – ivg

+1

另外,作爲一個方面的評論,我想注意,這種語言有一個很好的理由抵制你。它實際上是試圖告訴你,你做錯了什麼。創建curry函數沒有什麼好的理由,因爲每次應用它時都應該創建一個新對。所以,你'sum_pair'有一個可怕的開銷。更好的版本應該是:'| A(x,y) - > sum_pair x y' – ivg

回答

5

如果你定義的類型這樣可以使這項工作:

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

這意味着構造函數A實際上需要一個參數是一對。在你的原始定義中,它需要兩個不是一對的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的A構造函數的用法與此答案中的語法完全相同,但它們有不同的類型。爲什麼我們不能有構造函數的函數語法?是不是因爲他們不能被咖喱? – user3240588

+0

我們可以使用函數語法,參見'[@@ deriving variants]'。 – ivg