2013-04-29 106 views
1

說我有一個數據類型,它看起來像是否有ML型初始化程序?

datatype IntLt = ltObj of int * int * (int * int -> bool) 

也就是說,這個對象是一對整數與他們相應的操作。有沒有辦法在創建ltObj時自動調用帶有兩個參數的函數,並在結果爲false時引發異常?

也就是說,我正在尋找數據類型構造的構造函數類型過程,類似於Python中的__init__或C/C++/Java中的常見構造函數。我不希望爲此使用函數和簽名。

回答

4

在ML中執行這種不變量的慣用方式是通過模塊系統定義抽象數據類型(ADT)。下面是一個簡單的草圖:

signature INT_LT = 
sig 
    type int_lt 

    val int_lt : int * int * (int * int -> bool) -> int_lt 
    val pair : int_lt -> int * int 
    ... (* other abstract operations you might want *) 
end 

structure IntLt :> INT_LT = 
struct 
    type int_lt = int * int * (int * int -> bool) 

    fun int_lt(x, y, f) = 
     if f(x, y) then (x, y, f) else raise Domain 

    fun pair(x, y, f) = (x, y) 

    ... 
end 

具體地,注意使用不透明簽名歸屬:>這裏(也稱爲密封)的。它確保給定IntLt.int_lt類型的值,沒有人能夠知道其內部表示。這意味着沒有通過你的模塊接口,任何人都不能創建這種類型的值,也不能訪問它們。

現在,這使用簽名,但不是函子。 :)(也就是說,還有一種通過abstype構造創建ADT的方法,但它被認爲不贊成使用密封。)

1

如果您希望以後能夠在構造函數上進行模式匹配,則不存在—。

你會來那就是創造不你的願望什麼功能,並用它來構建IntLt值最接近的:

exception InvalidIntLt of int * int; 

fun createIntLt (a, b, f) = 
    if f(a, b) 
    then LtObj (a, b, f) 
    else raise InvalidIntLt (a, b); 

注意,它仍然將是有效的指定無效* IntLt通過使用構造函數的值。

如果您在結構中創建數據類型,則可以選擇防止出現這種情況。通過使用簽名,您可以在結構之外隱藏值構造函數的LtObj。但是請注意,這也意味着值構造函數不能用於結構外部的模式匹配。

*:在那f(a, b)不成立。

+0

我做謊言模式匹配... :) – JeremyKun 2013-05-01 02:22:46

+0

@Bean,即使當如果該模塊提供了將內部類型映射回某種外部可見類型的'視圖'功能,則可以將該類型封裝在模塊中,但仍可以進行模式匹配。在我的例子中'pair'函數可以被看作是這樣一個函數的一個簡單例子。 – 2013-05-04 14:44:05

相關問題