我稍微调查了Coq及其依赖类型。我对这一切只有最模糊的想法,但现在我想到我想要一个向量作为bool list
,其中向量的长度是该类型的一部分。
(这个问题可能是另一个问题的前身。在下一个问题中,如果我问它,我会问我是否可以恢复丢失的东西,当我使用typedef
时如下。 )
(对于这个问题,问题在底部)
以下是我想要的类型的要求:
bool list
,以便我可以直接或间接地在列表上进行模式匹配和递归,并且这就是我所拥有的:
typedef bitvec_4 = "{bl::bool list. length bl = 4}"
by(auto, metis Ex_list_of_length)
重要的是列表的长度是类型的一部分,因为我想使用带有definition
的类型,其中所有列表都具有相同的大小,就像这个简单的例子一样:
definition two_bv4_to_bv4 :: "bitvec_4 => bitvec_4 => bitvec_4" where
"two_bv4_to_bv4 x y = x"
在一个定理中,我不想要的是必须指定列表的长度。类型类最终会以某种方式发挥作用,但正如我所说,我希望在类型定义中指定长度。
n = 4
!! (最低幽默价值的技术笑话)现在,我尝试用这样的typedef
进行推广,其中长度是变量:
typedef bitvec_n = "{(bl::bool list, n::nat). length bl = n}"
by(auto)
这不好。在下一个这样的定义中,我的类型并不保证所有列表都具有相同的长度:
definition two_bvn_to_bvn :: "bitvec_n => bitvec_n => bitvec_n" where
"two_bvn_to_bvn x y = x"
我已尝试过类似bitvec_4
之类的类型。如果我不遇到大障碍,我可能会尝试大量使用它们。
我可以定义类似于上面的类型2的幂,最多比如1024位,以及反映它们共同属性的类型类。
但是,有更好的方法吗?我认为,使用bool list
。
根据曼努埃尔的回答,我在这里列出了一个独立的理论。
这主要是Manuel的来源重复,但最后,我的函数swap_bl
和swap_2bv
以及value
的最终用法显示了我的最终结果试图完成。我的评论强调了我脑海中存在的问题,可能我的最终应用程序显示了为什么我没有将HOL/Word
视为解决方案。
对于typedef
类型,间接进行模式匹配,类似于swap_bl
和2 bitvec
,我使用Abs
和Rep
函数反过来一起。正如曼努埃尔指出的那样,一个问题是,我可以向Abs
函数提供一个错误长度的bool list
,并且它不会给出错误。另一个大问题是由于使用了Abs
函数而导致的抽象违规。
这些问题,以及想知道我是否可以恢复使用value
typedef
类型的theory i141210ac__testing_out_manuels_answer
imports Main "~~/src/HOL/Library/Numeral_Type"
begin
(*Basic type definition.*)
typedef ('n::finite) bitvec = "{bs :: bool list. length bs = CARD('n)}"
morphisms bitvec_to_list Abs_bitvec
by (simp add: Ex_list_of_length)
setup_lifting type_definition_bitvec
lift_definition nth :: "('n::finite) bitvec => nat => bool" (infixl "$" 90)
is List.nth .
(*Can't use 'value' yet for 'nth', or I get an abstraction violation.*)
term "(Abs_bitvec [True,False] :: 2 bitvec) $ 1"
(*Truncate or fill the list: needed to set things up for 'value'.*)
definition set_length :: "nat => bool list => bool list" where
"set_length n xs = (if length xs < n
then xs @ replicate (n - length xs) False
else take n xs)"
lemma length_set_length [simp]: "length (set_length n xs) = n"
unfolding set_length_def by auto
definition list_to_bitvec :: "bool list => ('n::finite) bitvec" where
"list_to_bitvec xs = Abs_bitvec (set_length CARD('n) xs)"
(*Finishing the magic needed for 'value'.*)
lemma list_to_bitvec_code [code abstract]:
"bitvec_to_list (list_to_bitvec xs :: ('n::finite) bitvec)
= set_length CARD('n) xs"
unfolding list_to_bitvec_def by(simp add: Abs_bitvec_inverse)
(*Inverses for lists of length 2: no abstraction violations.*)
value "list_to_bitvec (bitvec_to_list x) :: 2 bitvec"
value "bitvec_to_list (list_to_bitvec x :: 2 bitvec)"
(*The magic now kicks in for 'value' and 'nth'. Understanding is optional.*)
value "(list_to_bitvec [True,False] :: 2 bitvec) $ 1" (*OUTPUT: False.*)
(*For my use, the primary context of all this is pattern matching on lists.
I can't pattern match on a 'typedef' type directly with 'fun', because
it's not a 'datatype'. I do it indirectly.*)
fun swap_bl :: "bool list => bool list" where
"swap_bl [a,b] = [b,a]"
|"swap_bl _ = undefined"
definition swap_2bv :: "2 bitvec => 2 bitvec" where
"swap_2bv bv = list_to_bitvec (swap_bl (bitvec_to_list bv))"
value "swap_2bv (list_to_bitvec [a,b] :: 2 bitvec)" (*
OUTPUT: "Abs_bitvec [b, a]" :: "2 bitvec" *)
(*Whether that's all a good idea, that's about the future, but it appears the
hard work, recovering the use of 'value', along with generalizing length,
has been done by Manuel, and the authors of Numeral_Type and its imports.*)
end
,这将成为我下一个问题的一部分,但所有这些都已在此处得到解答。
{{1}}
答案 0 :(得分:2)
Isabelle 不支持依赖类型,但仍有办法继续做你想做的事。例如,类型级自然数已经有一堆类型类和类型语法。
theory Scratch
imports Main "~~/src/HOL/Library/Numeral_Type"
begin
lemma "(UNIV :: 4 set) = {0,1,2,3}"
by (subst UNIV_enum) eval
如您所见,类型4
是一种包含0
到3
的数字的类型。顺便提一下,这也可以用于模运算中的计算:
lemma "((2 + 3) :: 4) = 1" by simp
lemma "((2 * 3) :: 4) = 2" by simp
您可以使用这些数字类型来参数化具有长度的位向量:
typedef ('n::finite) bitvec = "{bs :: bool list. length bs = CARD('n)}"
morphisms bitvec_to_list Abs_bitvec
by (simp add: Ex_list_of_length)
setup_lifting type_definition_bitvec
您可以通过将nth
函数从布尔列表提升到位向量来访问位向量的第n个元素,这会自动运行:
lift_definition nth :: "('n::finite) bitvec ⇒ nat ⇒ bool" (infixl "$" 90) is List.nth .
将布尔列表转换为位向量有点棘手,因为您输入的列表可能没有正确的长度;表达式list_to_bitvec [True] :: 2 bitvec
会出现问题,但显然存在问题。您可以通过返回undefined
来解决此问题,或者在此实例中更合适,使用False
填充列表或截断它以获得正确的长度:
definition set_length :: "nat ⇒ bool list ⇒ bool list" where
"set_length n xs = (if length xs < n then xs @ replicate (n - length xs) False else take n xs)"
lemma length_set_length[simp]: "length (set_length n xs) = n"
unfolding set_length_def by auto
现在我们可以定义一个将布尔列表转换为位向量的函数:
definition list_to_bitvec :: "bool list ⇒ ('n::finite) bitvec" where
"list_to_bitvec xs = Abs_bitvec (set_length CARD('n) xs)"
但是,我们不允许在代码方程中使用Abs_bitvec
;如果你试图评估,比如list_to_bitvec [True] :: 1 bitvec
,你会得到一个抽象违规。我们必须根据态射list_to_bitvec
:
lemma list_to_bitvec_code[code abstract]:
"bitvec_to_list (list_to_bitvec xs :: ('n::finite) bitvec) = set_length CARD('n) xs"
unfolding list_to_bitvec_def by (simp add: Abs_bitvec_inverse)
现在我们已基本完成并可以做到,例如这样:
definition myvec :: "4 bitvec" where "myvec = list_to_bitvec [True, False, True]"
value myvec
(* Output: "Abs_bitvec [True, False, True, False]" :: "4 bitvec" *)
value "myvec $ 2"
(* Output: "True" :: "bool" *)
请注意,始终必须使用其长度注释list_to_bitvec
的结果;伊莎贝尔可以不推断长度。
您可能还想查看Word
中的~~/src/HOL/Word/
理论;它使用NOT
,AND
,OR
等各种位操作来实现固定长度的机器字:
value "42 AND 23 :: 32 word"
(* Output: "2" :: "32 word" *)
value "293 :: 8 word"
(* Output: "37" :: "8 word" *)
value "test_bit (42 :: 8 word) 1"
(* Output: "True" :: "bool" *)
value "set_bit (42 :: 8 word) 2 True"
(* Output: "46" :: "8 word" *)
value "(BITS i. i < 4) :: 8 word"
(* Output: "15" :: "8 word" *)
另一种相关类型是src/HOL/Library/Multivariate_Analysis/Finite_Cartesian_Product
中的向量。