如何在Idris中指定数字范围作为类型?

时间:2015-02-10 07:24:48

标签: dependent-type idris

我一直在尝试使用Idris,似乎应该很容易指定某种类型来表示两个不同数字之间的所有数字,例如: NumRange 5 10是5到10之间所有数字的类型。我希望包含双精度/浮点数,但是用整数执行相同操作的类型同样有用。我该怎么做呢?

1 个答案:

答案 0 :(得分:9)

在实践中,您可以根据需要简单地检查边界,但您当然可以编写一种数据类型来强制执行此类属性。

一种直截了当的方法就是这样:

data Range : Ord a => a -> a -> Type where
  MkRange : Ord a => (x,y,z : a) -> (x >= y && (x <= z) = True) -> Range y z

我一直在Ord类型类上写它,尽管你可能需要专门化它。范围要求表示为等式,因此在构造时只需提供Refl,然后将检查属性。例如:MkRange 3 0 10 Refl : Range 0 10。这样的一个缺点是必须提取所包含的值的不便。当然,如果你想以编程方式构造一个实例,你需要提供边界确实满足的证明,或者在允许失败的某些上下文中进行,例如Maybe

我们可以毫不费力地为Nat写一个更优雅的例子,因为对于他们我们已经有了一个库数据类型来表示比较证明。特别是LTE,表示小于或等于。

data InRange : Nat -> Nat -> Type where
  IsInRange : (x : Nat) -> LTE n x -> LTE x m -> InRange n m

现在这个数据类型很好地封装了一个n≤x≤m的证明。对于许多临时应用程序来说,这将是一种过度杀伤,但它肯定会显示出如何使用依赖类型来实现此目的。