我的代码中有几个域类型用于区分不同类型的字符串,因此编译器可以阻止我以错误的顺序传递参数:
type Foo = string
type Bar = string
let baz (foo : Foo) (bar : Bar) = printfn "%A %A" foo bar
let f : Foo = "foo"
let b : Bar = "bar"
baz f b // this should be OK
baz b f // this shouldn't compile
Run Code Online (Sandbox Code Playgroud)
但是,这目前无法令人满意地工作,原因有两个:
null不是有效值的方法,所以我不能保证Foo实例永远不会null.有没有办法定义类型别名
a)引用/包装相同类型,但彼此不兼容,并且b)禁止null值,即使基础类型允许它?
kvb*_*kvb 10
别名可以自由替换,因此没有办法将它们用于此目的,但您可以使用单一案例区分联盟.使用智能构造函数来阻止使用null和私有实现(以便在模块之外的代码定义它们不能绕过智能构造函数),你应该基本上得到你想要的东西(尽管在运行时强制执行null的检查)而不是编译时间,遗憾地):
type Foo = private Foo of string with
static member OfString(s) =
if s = null then failwith "Can't create null Foo"
else Foo s
type Bar = private Bar of string with
static member OfString(s) =
if s = null then failwith "Can't create null Bar"
else Bar s
let baz (foo : Foo) (bar : Bar) = printfn "%A %A" foo bar
let f = Foo.OfString "foo"
let b = Bar.OfString "bar"
baz f b // ok
baz b f // type error
Run Code Online (Sandbox Code Playgroud)