受约束字符串值的类型

Tha*_*den 4 f# types refinement-type

刚刚开始我的 F# 之旅,是否可以定义一种类型,该类型仅限于一组特定的字符串值?例如 它只能表示值"Foo""Bar"并且"Baz",尝试为其分配任何其他值将引发错误,甚至在编译时失败。

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

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

接下来,我考虑使用 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"
Run Code Online (Sandbox Code Playgroud)

不太确定是否有任何一个是要走的路。

Mar*_*ann 5

正如人们在评论中指出的那样,总的来说,听起来您是在问 F# 是否具有称为优化类型的语言功能;它没有。

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

type Constrained =
    Foo | Bar | Baz
    override this.ToString () =
        match this with
        | Foo -> "Foo"
        | Bar -> "Bar"
        | Baz -> "Baz"
Run Code Online (Sandbox Code Playgroud)

这将使您能够Constrained使用内置string函数将任何值转换为您想要的字符串:

> string Foo;;
val it : string = "Foo"
> string Baz;;
val it : string = "Baz"
Run Code Online (Sandbox Code Playgroud)

如果您发现上述实现包含太多样板,您可以使用以下"%A"格式sprintf

type Constrained =
    Foo | Bar | Baz
    override this.ToString () = sprintf "%A" this
Run Code Online (Sandbox Code Playgroud)

由于"%A"使用反射,它会更慢,但行为是相同的。有一个建议可以使这方面的语言支持更好。