标称类型绑定到特定函数

时间:2016-09-20 00:48:04

标签: haskell types f# domain-driven-design

是否有支持定义只能通过特定功能实例化的类型的语言或类型系统。

示例可以是绑定到函数NonZeroInteger的类型CreateNonZeroInteger。任何外部代码都可以访问此类型的类型,接收和返回值。但至关重要的是,只能通过调用函数CreateNonZeroInteger

来创建该类型的值

NonZeroInteger名义上应该输入。具有相同结构的另一种类型的值不应与此类型相当或可投射。

2 个答案:

答案 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

类型本身仍可公开访问,但只能通过您提供的功能创建和分解。