我是依赖类型的新手(尽管他们有很大的不同,我正在尝试Idris和Coq)。
我试图表达以下类型:给定一个类型T和一个k nats n1,n2,... nk的序列,一个由长度为n1,n2,...的T序列组成的类型。 ..分别为。
即,k个向量的向量,其长度由参数给出。 这可能吗?
答案 0 :(得分:7)
您可以使用异构列表执行此操作,如下所示。
Require Vector.
Require Import List.
Import ListNotations.
Inductive hlist {A : Type} (B : A -> Type) : list A -> Type :=
| hnil : hlist B []
| hcons : forall a l, B a -> hlist B l -> hlist B (a :: l).
Definition vector_of_vectors (T : Type) (l : list nat) : Type :=
hlist (Vector.t T) l.
如果l
是您的长度列表,则vector_of_vectors T l
类型将与您描述的类型相对应。
例如,我们可以构造vector_of_vectors bool [2; 0; 1]
:
Section example.
Definition ls : list nat := [2; 0; 1].
Definition v : vector_of_vectors bool ls :=
hcons [false; true]
(hcons []
(hcons [true] hnil)).
End example.
此示例对您可以设置的向量使用一些符号:
Arguments hnil {_ _}.
Arguments hcons {_ _ _ _} _ _.
Arguments Vector.nil {_}.
Arguments Vector.cons {_} _ {_} _.
Delimit Scope vector with vector.
Bind Scope vector with Vector.t.
Notation "[ ]" := (@Vector.nil _) : vector.
Notation "a :: v" := (@Vector.cons _ a _ v) : vector.
Notation " [ x ] " := (Vector.cons x Vector.nil) : vector.
Notation " [ x ; y ; .. ; z ] " := (Vector.cons x (Vector.cons y .. (Vector.cons z Vector.nil) ..)) : vector.
Open Scope vector.
答案 1 :(得分:5)
在Idris中,除了创建自定义归纳类型之外,我们还可以重用标准类型的异构向量 - HVect
:
import Data.HVect
VecVec : Vect k Nat -> Type -> Type
VecVec shape t = HVect $ map (flip Vect t) shape
val : VecVec [3, 2, 1] Bool
val = [[False, False, False], [False, False], [False]] -- the value is found automatically by Idris' proof-search facilities
答案 2 :(得分:4)
为了完整起见,以下是Idris的解决方案,灵感来自James Wilcox发布的解决方案:
module VecVec
import Data.Vect
data VecVec: {k: Nat} -> Vect k Nat -> (t: Type) -> Type where
Nil : VecVec [] t
(::): {k, n: Nat} -> {v: Vect k Nat} -> Vect n t -> VecVec v t -> VecVec (n :: v) t
val: VecVec [3, 2, 3] Bool
val = [[False, True, False], [False, True], [True, False, True]]
此示例使用括号列表的自动转换到任何数据类型定义它们的基本构造函数Nil
和::
。