Gleam 中的不透明型別是一種自訂型別,只有定義該型別的模組才能建構或模式配對這種型別的值。當你希望某個型別只能以特定方式使用時,這就很有用。
不透明型別是用opaque關鍵字定義的。
pub opaque type PositiveInt {
PositiveInt(inner: Int)
}
這個PositiveInt型別適合用在需要整數、而且該整數必須大於或等於零的情境。一般的 Gleam Int無法勝任,因為它也可以是負數。
定義這個型別的模組可以定義一個函式來取得內部的整數值,也可以定義一個建立PositiveInt型別的函式,後者在傳入的值不是正數時會回傳錯誤。
pub fn from_int(i: Int) -> Result(PositiveInt, String) {
case i {
_ if i < 0 -> Error("Value must be positive")
_ -> Ok(PositiveInt(i))
}
}
pub fn to_int(i: PositiveInt) -> Int {
i.inner
}
有了這組 API,其他模組就無法建構出帶有負數值的PositiveInt,因此任何接受PositiveInt的函式都能確定這個值是正數。
眼尖的學生應該已經發現,前一個練習裡的TreasureChest型別其實沒那麼安全!
使用get_treasure函式時,你必須提供密碼,但你還是可以解構TreasureChest型別,在不知道密碼的情況下取得寶藏。
我們就用不透明型別來解決這個問題吧。
TreasureChest不透明型別TreasureChest包含兩個欄位:
String型別的密碼。TreasureChest型別必須是不透明的。
create函式這個函式接受兩個引數:
String型別的密碼。函式會回傳一個TreasureChest,其中包含密碼和該值。
如果密碼少於 8 個字元,函式應該回傳一個錯誤,內容為Password must be at least 8 characters long。
open函式這個函式接受兩個引數:
TreasureChest。String型別的密碼。如果密碼與TreasureChest裡的密碼相符,函式應該回傳寶藏,否則應該回傳一個錯誤,內容為Incorrect password。