f# - 创建一个由 int 和 float 的子集组成的类型'
问题描述
假设我只想代表这 8 个温度:
98F
99F
100F
101F
37.0C
37.5C
38.0C
38.5C
我会有一个类型,例如:
type Temp =
| F of int
| C of float
也许而不是使用int
and float
,我会使用更具体的类型?
如何创建只允许 8 种不同温度的类型?
解决方案
好吧,如果你非常有信心只需要 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
。
推荐阅读
- java - 如何四舍五入到合理的值java
- ios - Swift - SKSprite Kit - 从 FileBrowser Closure 更改 Gamescene 变量
- r - 使用 sprintf() 简洁
- python - MySQL 列(字段)最大宽度
- postgresql - 如何在 node-pg 中使用变量作为表名?
- entity-framework-core - EF Core 3.1 未正确翻译查询
- wordpress - 显示与 /wp-content/uploads/ 中的图像不同的图像的链接
- ffmpeg - FFMPEG Concat 不同的视频类型以及图像和 Gif
- php - 在 SQL 语句上方填充 PHP 变量
- flutter - 如何在颤振应用程序中覆盖元素?