首页 文章

受约束的字符串值的类型

提问于
浏览
4

刚开始我的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 回答

  • 4

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

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

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

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

    > 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" 使用了反射,因此在这方面可以更好地支持语言 .

相关问题