是否支持定義只能通過特定功能實例化的類型的語言或類型系統。綁定到特定功能的名義類型
一個示例可能是與函數CreateNonZeroInteger
綁定的類型NonZeroInteger
。任何外部代碼都可以訪問該類型,接收和返回此類型的值。但重要的是,只能通過調用函數CreateNonZeroInteger
NonZeroInteger
應該名義上鍵入來創建該類型的值。具有相同結構的另一種類型的值不應與此類型相比或可鑄造。
是否支持定義只能通過特定功能實例化的類型的語言或類型系統。綁定到特定功能的名義類型
一個示例可能是與函數CreateNonZeroInteger
綁定的類型NonZeroInteger
。任何外部代碼都可以訪問該類型,接收和返回此類型的值。但重要的是,只能通過調用函數CreateNonZeroInteger
NonZeroInteger
應該名義上鍵入來創建該類型的值。具有相同結構的另一種類型的值不應與此類型相比或可鑄造。
創建一個類型,定義一個函數來創建該類型的值,然後導出類型和函數,但不是而是該類型的數據構造函數。例如,在Haskell,給你的例子:
module My.Module.NonZeroInteger (NonZeroInteger, createNonZeroInteger) where
newtype NonZeroInteger = NonZeroInteger Integer
deriving (Show, Eq, Ord)
createNonZeroInteger :: Integer -> Maybe NonZeroInteger
createNonZeroInteger 0 = Nothing
createNonZeroInteger x = Just $ NonZeroInteger x
的My.Module.NonZeroInteger
消費者將能夠創建NonZeroInteger
類型的值,但由於數據的構造不出口,他們將永遠不會成爲能夠創造NonZeroInteger
小號這是內部0
。
自定義構造函數,在這種情況下爲createNonZeroInteger
,傳統上稱爲「smart constructor」。
我真的希望類型本身綁定到簽名中的函數,而不是利用模塊封裝。但這真的很有幫助,並回答了這個問題。 –
我覺得值得在這裏記錄下來,你可以做到亞歷克西斯金在F#中建議的完全一樣的東西,通過使工會案例構造函數private
。
type NonZeroInteger = private NonZeroInteger of int
let tryCreateNonZeroInteger = function
|0 -> None
|x -> Some <| NonZeroInteger x
該類型本身仍然是可公開訪問的,但它只能通過您提供的函數創建和分解。
我認爲這通常是用隱藏數據構造函數的模塊來完成的,並暴露了一個包裝數據構造函數的函數。在這裏看到最佳答案:http://stackoverflow.com/questions/39531032/using-types-to-force-correctness – zoran119
在f#中,您可以使用訪問修飾符,但它會很醜陋 –
「*是否有語言或類型系統它支持定義只能通過特定函數實例化的類型。*「好吧,C++ for one;但我不知道任何基於_Hindley-Milner的類型系統完全支持它,這似乎是你實際要求的。 – ildjarn