这是Existing constants (e.g. constructors) in type class instantiations的衍生问题。
简短的问题是:如何防止free_constructors
引起的错误,以便我可以将下面包含的两种理论结合起来。
我已经坐了几个月了。另一个问题帮助我前进(看来)。感谢值得感谢的人。
这里真正的问题是关于重载符号,虽然看起来我现在只有命名空间问题。
此时,这不是必需品,只是不方便两种理论必须使用。如果系统允许,所有这些都会消失,但无论如何我都要求获得一些额外的信息。
这里的重要解释是解释动机,这可能会导致获得一些额外的信息。我解释一下,然后加入S1.thy
,发表一些评论,然后加入S2.thy
。
基本思想是我可能有5种不同形式的二进制单词,这些单词已经用datatype
定义,我想定义一些二进制和十六进制表示法,这些表示法已经为所有5种类型重载。
我不知道一切皆有可能,但过去告诉我(由其他人告诉我的事情)如果我想要代码生成,那么我应该使用类型类来获得类型类带来的魔力。 / p>
接下来是理论S1.thy
。我所做的是为类型类bool
和zero
实例化one
,然后使用free_constructors
设置符号0
和1
用作bool
构造函数True
和False
。它似乎工作。这本身就是我特别想要的,但不知道该怎么做。
然后我尝试使用示例datatype
,BitA
做同样的事情。它不起作用,因为使用case_BitA
定义BitA
时会创建常量datatype
。它会引发冲突。
我的进一步评论是在THY。
theory S1
imports Complex_Main
begin
declare[[show_sorts]]
(*---EXAMPLE, NAT 0: IT CAN BE USED AS A CONSTRUCTOR.--------------------*)
fun foo_nat :: "nat => nat" where
"foo_nat 0 = 0"
(*---SETTING UP BOOL TRUE & FALSE AS 0 AND 1.----------------------------*)
(*
I guess it works, because 'free_constructors' was used for 'bool' in
Product_Type.thy, instead of in this theory, like I try to do with 'BitA'.
*)
instantiation bool :: "{zero,one}"
begin
definition "zero_bool = False"
definition "one_bool = True"
instance ..
end
(*Non-constructor pattern error at this point.*)
fun foo1_bool :: "bool => bool" where
"foo1_bool 0 = False"
find_consts name: "case_bool"
free_constructors case_bool for "0::bool" | "1::bool"
by(auto simp add: zero_bool_def one_bool_def)
find_consts name: "case_bool"
(*found 2 constant(s):
Product_Type.bool.case_bool :: "'a∷type => 'a∷type => bool => 'a∷type"
S1.bool.case_bool :: "'a∷type => 'a∷type => bool => 'a∷type" *)
fun foo2_bool :: "bool => bool" where
"foo2_bool 0 = False"
|"foo2_bool 1 = True"
thm foo2_bool.simps
(*---TRYING TO WORK A DATATYPE LIKE I DID WITH BOOL.---------------------*)
(*
There will be 'S1.BitA.case_BitA', so I can't do it here.
*)
datatype BitA = A0 | A1
instantiation BitA :: "{zero,one}"
begin
definition "0 = A0"
definition "1 = A1"
instance ..
end
find_consts name: "case_BitA"
(*---ERROR NEXT: because there's already S1.BitA.case_BitA.---*)
free_constructors case_BitA for "0::BitA" | "1::BitA"
(*ERROR: Duplicate constant declaration "S1.BitA.case_BitA" vs.
"S1.BitA.case_BitA" *)
end
case_BitA
似乎需要free_constructors
进行设置,而且我想到也许我可以通过在一个理论中使用datatype
来使其工作,并使用free_constructors
在另一个理论中。
似乎有效。有没有办法将这两种理论结合起来?
theory S2
imports S1
begin
(*---HERE'S THE WORKAROUND. IT WORKS BECAUSE BitA IS IN S1.THY.----------*)
(*
I end up with 'S1.BitA.case_BitA' and 'S2.BitA.case_BitA'.
*)
declare[[show_sorts]]
find_consts name: "BitA"
free_constructors case_BitA for "0::BitA" | "1::BitA"
unfolding zero_BitA_def one_BitA_def
using BitA.exhaust
by(auto)
find_consts name: "BitA"
fun foo_BitA :: "BitA => BitA" where
"foo_BitA 0 = A0"
|"foo_BitA 1 = A1"
thm foo_BitA.simps
end
答案 0 :(得分:2)
命令free_constructors
总是为case表达式创建给定名称的新常量,并以与datatype
相同的方式命名生成的定理,因为datatype
internaly调用{{ 1}}。
因此,您必须在更改名称空间的上下文中发出命令free_constructors
。例如,使用区域设置:
free_constructors
之后,您可以同时使用locale BitA_locale begin
free_constructors case_BitA for "0::BitA" | "1::BitA" ...
end
interpretation BitA!: BitA_locale .
和A0
作为模式匹配方程中的构造函数以及A1
和0
,但不应将它们混合在一个等式中。然而,1
和A0
仍然是伊莎贝尔的不同常数。这意味着您可能必须在校样期间手动将一个转换为另一个,并且代码生成仅适用于其中一个。您必须设置代码生成器,在代码方程式中将0
替换为A0
,将0
替换为A1
(反之亦然)。为此,您希望将方程1
和A0 = 0
声明为A1 = 1
,但您也可能希望在ML中编写自己的预处理函数来替换[code_unfold]
和{ {1}}在代码方程式的左侧,有关详细信息,请参阅代码生成器教程。
请注意,如果A0
是多态数据类型,则A1
和BitA
等包将继续使用旧的构造函数集。
鉴于这些问题,我真的会按照my answer中的描述对另一个问题进行手动定义。这可以在以后为您节省很多潜在的问题。另外,如果您真的只对符号感兴趣,可能需要考虑BNF
。它与代码生成完美配合,比类型类更灵活。但是,您不能抽象地谈论重载符号,即,必须将重载常量的每次出现都消除歧义为单个用例。在证明方面,这不应该是一个限制,因为你不假设重载常量。就抽象符号的定义而言,您还必须在那里重复重载(或者对语言环境中的重载定义进行抽象并多次解释语言环境)。