使用类型 类 重载构造函数的符号(现在是命名空间问题)

Using type classes to overload notation for constructors (now a namespace issue)

这是的衍生题。

简短的问题是:如何防止由于 free_constructors 而发生的错误,以便我可以结合下面包含的两个理论。

我已经坐了几个月了。另一个问题帮助我前进(看起来)。感谢该感谢的人

这里的真正问题是关于重载符号,尽管看起来我现在只是遇到了命名空间问题。

在这一点上,这不是必需的,只是不得不使用两种理论带来的不便。如果系统允许,这一切都会消失,但我还是要问,以便有可能获得一些额外的信息。

这里的主要解释是解释动机,这可能会导致获得一些额外的信息。我解释一些,然后包含 S1.thy,发表一些评论,然后包含 S2.thy.

动机:使用句法类型类重载多个二进制数据类型的符号

基本思想是我可能有 5 种不同形式的二进制字,它们已用 datatype 定义,我想定义一些二进制和十六进制符号,这些符号对所有 5 种类型都过载。

我不知道什么是可能的,但过去告诉我(通过其他人告诉我的事情),如果我想要代码生成,那么我应该使用类型 类,以获得魔法附带 类.

类型

第一个理论,S1

接下来是理论S1.thy。我所做的是为类型 类 zeroone 实例化 bool,然后使用 free_constructors 设置符号 01 用作 bool 构造函数 TrueFalse。它似乎工作。这本身就是我特别想要的东西,但不知道该怎么做。

然后我尝试用一​​个例子做同样的事情 datatypeBitA。它不起作用,因为常量 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

第二种理论,S2

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

命令 free_constructors 总是为 case 表达式创建一个给定名称的新常量,并以与 datatype 相同的方式命名生成的定理,因为 datatype 内部调用free_constructors。 因此,您必须在更改名称 space 的上下文中发出命令 free_constructors。例如,使用语言环境:

locale BitA_locale begin
free_constructors case_BitA for "0::BitA" | "1::BitA" ...
end
interpretation BitA!: BitA_locale .

之后,您可以同时使用A0A1作为模式匹配方程的构造子以及01,但您不应该将它们混合在一个单方程。然而,A00 对伊莎贝尔来说仍然是不同的常量。这意味着您可能必须在证明期间手动将一个转换为另一个,并且代码生成仅适用于其中一个。您必须设置代码生成器以在代码方程式中将 A0 替换为 0 并将 A1 替换为 1(反之亦然)。为此,您想将方程式 A0 = 0A1 = 1 声明为 [code_unfold],但您可能还想用 ML 编写自己的预处理器函数来替换 A0A1在代码方程式的左侧,详情请参阅代码生成器教程。

请注意,如果 BitA 是多态数据类型,则 BNFlifting 等包将继续使用旧的构造函数集。

考虑到这些问题,我真的会按照 中描述的那样手动定义类型到另一个问题。这为您以后避免了很多潜在的问题。另外,如果你真的只对符号感兴趣,你可能需要考虑 adhoc_overloading。它与代码生成完美配合,并且比 type 类 更灵活。但是,您不能抽象地谈论重载符号,即重载常量的每次出现都必须消除歧义为单个用例。就证明而言,这不应该是一个限制,因为您对重载常量没有任何假设。就抽象符号上的定义而言,您还必须在那里重复重载(或者在语言环境中抽象重载定义并多次解释语言环境)。