首页 > 解决方案 > 创建一个由 int 和 float 的子集组成的类型'

问题描述

假设我只想代表这 8 个温度:

98F
99F
100F
101F
37.0C
37.5C
38.0C
38.5C

我会有一个类型,例如:

type Temp = 
  | F of int
  | C of float

也许而不是使用intand float,我会使用更具体的类型?

如何创建只允许 8 种不同温度的类型?

标签: f#

解决方案


好吧,如果你非常有信心只需要 8 个温度,你可以这样做:

type AllowedTemperatures = 
            | F98
            | F99
            | F100
            | F101
            | C370
            | C375
            | C380
            | C385

也就是说,如果你想改用你的类型Temp,这不容易做到,因为它基本上需要具有依赖类型的能力,这是 F# 没有的功能(尽管显然有一个我没有尝试过的将其添加到语言中)。你可以尝试这样的事情:

type Temp = 
  | F of int
  | C of float with
  static member fromInt value =
    if value <> 98 && value <> 99 && value <> 100 && value <> 101 then
        raise <| System.ArgumentOutOfRangeException ("value")
    else
        F value
  static member fromFloat value =
    if value <> 37.0 && value <> 37.5 && value <> 38.0 && value <> 38.5 then
        raise <| System.ArgumentOutOfRangeException ("value")
    else
        C value

并始终通过静态成员构建您的可区分工会成员。但这不会阻止某人直接调用构造函数。

编辑:感谢 AMieres 的建议,降低错误调用 F 的可能性的一种方法是在Temp. 例如,您可以执行以下操作:

type Temp = 
  | F of int
  | C of float



let F value  = 
    if value <> 98 && value <> 99 && value <> 100 && value <> 101 then
        raise <| System.ArgumentOutOfRangeException ("value")
    else
        F value

但是,仍然有人可以打电话Temp.F


推荐阅读