受约束的字符串值的类型

时间:2016-04-21 17:59:50

标签: types f# refinement-type

刚开始我的F#之旅,是否可以定义一个受限于特定字符串值集的类型? F.ex.它只能表示值"Foo""Bar""Baz",尝试为其分配任何其他值将导致错误,甚至在编译时更好地失败。

更新: 到目前为止,我考虑过创建一个字符串类型并使用create函数:

type Constrained = string
let createConstrained (constrained : Constrained) = 
    match constrained with
        | "foo" -> constrained
        | "bar" -> constrained
        | "baz" -> constrained
        | _ -> failwith "Can be only foo, bar or baz"

接下来,我考虑使用DU和某种函数,它根据选项返回字符串(是正确的名称吗?):

type Constrained = FOO | BAR | BAZ
let constrainedString constrained =
    match constrained with
        | FOO -> "foo"
        | BAR -> "bar"
        | BAZ -> "baz"
        | _ -> failwith "Can only be foo, bar or baz"

不确定是否有任何一种方法可以使用。

1 个答案:

答案 0 :(得分:4)

正如人们在评论中指出的那样,一般来说,听起来你在问F#是否具有称为细化类型的语言特征;它没有。

但是,在您的特定示例中,您可以简单地定义一个有区别的联合并覆盖其ToString方法:

type Constrained =
    Foo | Bar | Baz
    override this.ToString () =
        match this with
        | Foo -> "Foo"
        | Bar -> "Bar"
        | Baz -> "Baz"

这样您就可以使用内置的Constrained函数将任意string值转换为所需的字符串:

> string Foo;;
val it : string = "Foo"
> string Baz;;
val it : string = "Baz"

如果您发现上述实施包含太多样板文件,则可以将"%A"格式与sprintf一起使用:

type Constrained =
    Foo | Bar | Baz
    override this.ToString () = sprintf "%A" this

由于"%A"使用反射,它会变慢,但行为是相同的。有a suggestion在这个领域提供更好的语言支持。