是否有支持定义只能通过特定功能实例化的类型的语言或类型系统。
示例可以是绑定到函数NonZeroInteger
的类型CreateNonZeroInteger
。任何外部代码都可以访问此类型的类型,接收和返回值。但至关重要的是,只能通过调用函数CreateNonZeroInteger
NonZeroInteger
名义上应该输入。具有相同结构的另一种类型的值不应与此类型相当或可投射。
答案 0 :(得分:7)
创建一个类型,定义一个函数来创建该类型的值,然后导出类型和函数,但不类型的数据构造函数。例如,在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”。
答案 1 :(得分:2)
我认为值得在此记录下来,你可以通过制作工会案例构造函数private
来完成与Alexis King在F#中建议完全相同的事情。
type NonZeroInteger = private NonZeroInteger of int
let tryCreateNonZeroInteger = function
|0 -> None
|x -> Some <| NonZeroInteger x
类型本身仍可公开访问,但只能通过您提供的功能创建和分解。