f# - 如何创建其值只能在有效范围内的类型?

标签 f#

如何创建其值只能在有效范围内的类型?

大多数静态类型语言都提供数字类型,其中每种类型都支持一定范围的值。

int是这种类型的一个例子。

支持以下内容:

Make illegal states unrepresentable



如何创建一个类型,使得超出范围的值分配会在编译时导致错误?

例如:
Type PositiveInteger//范围是 0 到 2,147,483,647

更新

我试过这个:
type PositiveInteger = private PInt of int with
    static member FromInt i =
       if i <= 0 then failwith "out of range" else PInt i

let isSuccessful = 
    PInt -1

但是,当我希望它在编译时抛出“超出范围”时,上面的代码仍然可以编译。
可以说编译时不支持这是否公平?

最佳答案

让我们继续这个例子(并将其扩展为正 p <=> p > 0)

你总是可以去使用一些数学(这里使用对 peano axioms 的轻微修改来定义正自然数):

type PositiveInteger =
   | One
   | Succ of PositiveInteger

哪个会有更大的范围

当然这有点难用:
let one = One
let two = Succ one
...
let rec add a b =
     match (a,b) with
     | (One, b)    -> Succ b
     | (Succ a, b) -> Succ (add a b)

这通常不够有效(尽管它通常用于类型级别......如果语言支持的话)

所以可能大多数人会使用带有某种智能构造函数的快速失败方法:
type PositiveInteger = private PInt of int with
    static member FromInt i =
       if i <= 0 then failwith "out of range" else PInt i

如果你不喜欢 with,这个也应该编译:
type PositiveInteger = 
    private | PInt of int
    static member FromInt i =
        if i <= 0 then failwith "out of range" else PInt i

关于f# - 如何创建其值只能在有效范围内的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36003602/

相关文章:

f# - F# 显式类型参数的用例是什么?

F# 使用 monad (ROP) 来组合具有两个参数的函数

c# - F# 代码调用包含异常运行的 Func 参数的 c# 方法

f# - 纸牌游戏的遗传算法(Dominion)

f# - 如何在 F# 中编写高效的列表/序列函数? (mapFoldWhile)

generics - 是否可以在 F# 中为参数化泛型类型定义扩展方法(就像在 C# 中一样)

.net-core - 起订量:如何在没有占位符接口(interface)的情况下模拟 F# 中的函数?

generics - F#:函数参数默认为类中的 obj

f# - 如何组合选项和结果

f# - 模式匹配是获取与联合案例关联的数据的唯一方法吗?