Types 有没有一种方法可以使用OCaml';s键入系统以强制执行有关值的规则?
我是OCaml的新手,一直在探索类型系统的功能。我有两个问题Types 有没有一种方法可以使用OCaml';s键入系统以强制执行有关值的规则?,types,ocaml,Types,Ocaml,我是OCaml的新手,一直在探索类型系统的功能。我有两个问题 在这种记录类型中,有没有一种方法可以使用OCaml的类型系统来强制执行nums1+nums2=all_nums的规则 type foo={all_nums:int-list;nums1:int-list;nums2:int-list;};; e、 如果nums1=[1]和nums2=[2;3],那么所有的num都必须是[1;2;3] 在该记录类型中,是否有方法使用类型系统强制nums1中的任何项都不应同时位于nums2中,即它们的交
type foo={all_nums:int-list;nums1:int-list;nums2:int-list;};;
e、 如果nums1=[1]和nums2=[2;3],那么所有的num都必须是[1;2;3]
type bar={nums1:int-list;nums2:int-list;};;
e、 g.如果nums1=[1],nums2也不能包含1
提前感谢。是和否。将调用依赖于运行时值的类型,而OCaml不完全支持依赖类型。传统编程语言通常不支持它们,因为它们使编程变得相当繁琐。例如,从理论上讲,OCaml有足够的依赖类型来支持您的案例,但您不能使用
list
或int
,并且必须对它们使用GADT表示。最终,它几乎无法使用。因为OCaml类型的系统仍然是静态的,所以它必须在程序执行之前检查您的程序是否对所有可能的集合有效。这将极大地限制可类型化程序集
然而,使用抽象类型和幻影类型相结合,可以对任意不变量进行编码,并依赖类型系统来保存它。诀窍是定义一个小的可信内核,其中不变量是手动执行的
以你的第一个例子来说
module Foo : sig
type t
val create : int list -> int list -> int list -> (t,error) result
end = struct
type t = {all_nums: int list; nums1: int list; nums2: int list;}
type error = Broken_invariant
let create all_nums nums1 nums2 =
if invariant_satisfied all_nums nums1 nums 2
then Ok {all_nums; nums1; nums2}
else Error Broken_invariant
end
使用这种密封表示法,不可能在模块Foo
之外创建Foo.t
类型的值,因为满足不变量
的值不是真的。因此,您的Foo
是受信任的内核—您需要检查是否保留了不变量的唯一地方。其余部分由打字系统负责
如果使用幻像类型,则可以对更复杂的不变量进行编码,并使其更具表现力,例如
module Number : sig
type 'a t
type nat
type neg
type any = (nat t, neg t) Either.t
val zero : nat t
val one : nat t
val of_int : int -> any
val padd : nat t -> nat t -> nat t
val gadd : 'a t -> 'b t -> any
end = struct
type 'a t = int
type nat
type neg
type any = (nat t, neg t) Either.t
let zero = 0
let one = 1
let of_int x = if x < 0 then Right x else Left x
let padd x y = x + y (* [see note 2] *)
let gadd x y = of_int (x + y)
end
模块编号:sig
a型t型
类型nat
neg型
键入any=(nat t,neg t)或.t
val zero:nat t
瓦尔一号:纳特
val of_int:int->any
val padd:nat t->nat t->nat t
val gadd:'a t->'b t->any
end=struct
输入'a t=int
类型nat
neg型
键入any=(nat t,neg t)或.t
设0=0
设1=1
设_int x=如果x<0,则为右x,否则为左x
让padd x y=x+y(*[见注2]*)
设gadd x y=of_int(x+y)
结束
其中or.t
类型定义为type('a,'b)t=a的左侧| b的右侧
笔记
注1。您的第一个示例可以以不可能破坏不变量的方式进行编码,例如,您可以在all_nums
中表示您的类型{nums1:int list;nums2:int list}
并将all_nums
定义为函数,让all_nums=list.append
附注2。事实上,由于OCaml和许多其他编程语言一样,使用模块化算术,两个正数相加可能导致负数,因此我们的示例是拙劣的。但为了举例,让我们忽略这一点:)