說我有一個數據類型,它看起來像是否有ML型初始化程序?
datatype IntLt = ltObj of int * int * (int * int -> bool)
也就是說,這個對象是一對整數與他們相應的操作。有沒有辦法在創建ltObj時自動調用帶有兩個參數的函數,並在結果爲false時引發異常?
也就是說,我正在尋找數據類型構造的構造函數類型過程,類似於Python中的__init__
或C/C++/Java中的常見構造函數。我不希望爲此使用函數和簽名。
說我有一個數據類型,它看起來像是否有ML型初始化程序?
datatype IntLt = ltObj of int * int * (int * int -> bool)
也就是說,這個對象是一對整數與他們相應的操作。有沒有辦法在創建ltObj時自動調用帶有兩個參數的函數,並在結果爲false時引發異常?
也就是說,我正在尋找數據類型構造的構造函數類型過程,類似於Python中的__init__
或C/C++/Java中的常見構造函數。我不希望爲此使用函數和簽名。
在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的方法,但它被認爲不贊成使用密封。)
如果您希望以後能夠在構造函數上進行模式匹配,則不存在—。
你會來那就是創造不你的願望什麼功能,並用它來構建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)
不成立。
我做謊言模式匹配... :) – JeremyKun 2013-05-01 02:22:46
@Bean,即使當如果該模塊提供了將內部類型映射回某種外部可見類型的'視圖'功能,則可以將該類型封裝在模塊中,但仍可以進行模式匹配。在我的例子中'pair'函數可以被看作是這樣一個函數的一個簡單例子。 – 2013-05-04 14:44:05