Types 是否可以在OCaml/ReasonML上实现值索引数据类型?

Types 是否可以在OCaml/ReasonML上实现值索引数据类型?,types,ocaml,agda,Types,Ocaml,Agda,我最近被介绍给agda,这引起了我的注意: data Vector (A : Set) : Nat → Set where [] : Vector A zero _∷_ : {n : Nat} → A → Vector A n → Vector A (suc n) _++_ : ∀ {a m n} {A : Set a} → Vec A m → Vec A n → Vec A (m + n) [] ++ ys = ys (x ∷ xs) ++ ys = x ∷ (xs +

我最近被介绍给agda,这引起了我的注意:

data Vector (A : Set) : Nat → Set where
  []  : Vector A zero
  _∷_ : {n : Nat} → A → Vector A n → Vector A (suc n)

_++_ : ∀ {a m n} {A : Set a} → Vec A m → Vec A n → Vec A (m + n)
[]       ++ ys = ys
(x ∷ xs) ++ ys = x ∷ (xs ++ ys)
我试图在OCaml中实现这种数组,但我意识到我不能将类型索引到值上。我设法对长度使用类型,但我不能强制执行连接检查Vec A m→ 维卡→ 向量A m+n


是否可行?

OCaml不支持依赖类型,因此不可能有值索引类型。然而,对于长度索引列表,仅使用GADT就可以获得相当大的收益

起点是定义一个类型构造来表示succ运算符

然后给出了Peano自然数的经典定义

type ('x,'x_plus_n) nat =
  | Zero: ('n, 'n) nat (* n + 0 = n *)
  | Succ: ('x,'x_plus_n) nat -> ('x, 'x_plus_n succ) nat
  (* succ ( n + x ) = n + succ x *)
let zero = Zero
let one = Succ zero
这种表示法的优点是,可以通过声明将x+y添加到n可以分解为n+x+y来定义加法:

从这些定义中,定义长度索引列表只是将此自然整数编码存储在列表类型中的问题:

type ('elt,'x,'x_plus_length)  nlist =
  | []: ('elt, 'n,'n) nlist
  | (::) : 'elt * ('elt, 'n, 'n_plus_length) nlist
     -> ('elt, 'n,'n_plus_length succ) nlist
我们在这里使用的事实是::是一个中缀类型构造函数 [1;2;3]只是1::2::3::[]的一些语法糖 这意味着我们可以写作

let l = [1;2;3]
let l' = [1;2]
l=l'失败,并出现类型错误

使用此定义,只需使用

let rec len: type inf sup. ('elt, inf,sup) nlist -> (inf,sup) nat =
  function
  | [] -> Zero
  | _ :: q -> Succ (len q)
将两个列表连在一起只需要一点技巧就可以确定类型参数的顺序:

let rec (@): type inf mid sup.
  ('elt,mid,sup) nlist -> ('elt,inf,mid) nlist -> ('elt, inf,sup) nlist =
fun left right -> match left with
  | [] -> right
  | a :: q -> a :: (q @ right)

事实上,使用这些类型的列表的主要障碍是值限制,这使得保持所有涉及泛型的类型变量而不是弱多态性非常困难。

OCaml不支持依赖类型,因此不可能有值索引类型。然而,对于长度索引列表,仅使用GADT就可以获得相当大的收益

起点是定义一个类型构造来表示succ运算符

然后给出了Peano自然数的经典定义

type ('x,'x_plus_n) nat =
  | Zero: ('n, 'n) nat (* n + 0 = n *)
  | Succ: ('x,'x_plus_n) nat -> ('x, 'x_plus_n succ) nat
  (* succ ( n + x ) = n + succ x *)
let zero = Zero
let one = Succ zero
这种表示法的优点是,可以通过声明将x+y添加到n可以分解为n+x+y来定义加法:

从这些定义中,定义长度索引列表只是将此自然整数编码存储在列表类型中的问题:

type ('elt,'x,'x_plus_length)  nlist =
  | []: ('elt, 'n,'n) nlist
  | (::) : 'elt * ('elt, 'n, 'n_plus_length) nlist
     -> ('elt, 'n,'n_plus_length succ) nlist
我们在这里使用的事实是::是一个中缀类型构造函数 [1;2;3]只是1::2::3::[]的一些语法糖 这意味着我们可以写作

let l = [1;2;3]
let l' = [1;2]
l=l'失败,并出现类型错误

使用此定义,只需使用

let rec len: type inf sup. ('elt, inf,sup) nlist -> (inf,sup) nat =
  function
  | [] -> Zero
  | _ :: q -> Succ (len q)
将两个列表连在一起只需要一点技巧就可以确定类型参数的顺序:

let rec (@): type inf mid sup.
  ('elt,mid,sup) nlist -> ('elt,inf,mid) nlist -> ('elt, inf,sup) nlist =
fun left right -> match left with
  | [] -> right
  | a :: q -> a :: (q @ right)
事实上,使用这些类型的列表的主要障碍是值限制,这使得保持所有涉及泛型的类型变量而不是弱多态性非常困难