如何在Isabelle中定义部分函数?
我试图用如何在Isabelle中定义部分函数?,isabelle,Isabelle,我试图用partial\u函数关键字定义一个分部函数。它不起作用。下面是一个最能表达直觉的例子: partial_function (tailrec) oddity :: "nat => nat" where "oddity Zero = Zero " | "oddity (Succ (Succ n)) = n" 然后我尝试了以下方法: partial_function (tailrec) oddity :: "nat => nat" where "oddity arg =
partial\u函数
关键字定义一个分部函数。它不起作用。下面是一个最能表达直觉的例子:
partial_function (tailrec) oddity :: "nat => nat"
where
"oddity Zero = Zero "
| "oddity (Succ (Succ n)) = n"
然后我尝试了以下方法:
partial_function (tailrec) oddity :: "nat => nat"
where
"oddity arg = ( case arg of (Succ (Succ n)) => n
| Zero => Zero
)"
partial_function (tailrec) oddity :: "nat => nat"
where
"oddity (Succ(Succ n)) = n
| oddity Zero = Zero"
partial_function (tailrec) oddity :: "nat => nat"
where
"oddity n =
(if n = Zero then Zero
else if (n >= 2)
then do { m ← oddity (n-2); m })"
他们都没有工作。我想我的尝试存在概念和语法问题,这些是什么?您的定义有两个问题:
partial_函数
不支持左侧的模式匹配。这必须使用右侧的case
表达式进行模拟nat
的构造函数是Suc
和0
,而不是Suc
和Zero
。这就是为什么您的case表达式生成错误,即Succ
和Zero
不是数据类型构造函数,并且parital_函数
抱怨Zero
是右侧的额外变量partial_function (tailrec) oddity :: "nat => nat"
where "oddity arg = (case arg of (Suc (Suc n)) => n | 0 => 0 )"
通过使用来自~/src/HOL/Library/Simps\u case\u Conv的simp\u of\u case
转换,您可以通过模式匹配恢复简化规则:
simps_of_case oddity_simps[simp]: oddity.simps
thm oddity_simps
关于上一个示例的一些评论:
在Isabelle/HOL中没有if-then
而没有else
。因此出现了语法错误。要解决此问题,您必须为最后一个if
提供else
-分支,或者重写定义。例如
partial_function (tailrec) oddity :: "nat ⇒ nat"
where
"oddity n = (
if n = 0 then 0
else if n ≥ 2 then do { m ← oddity (n - 2); m }
else undefined)"
此时将出现关于“未解决的临时重载”的错误。记住,do符号只是语法上的糖分。让我们试着通过查看do块来了解实际发生了什么
term "do { m ← oddity (n - 2); m }"
由于仍然存在未解决的重载,让我们将m
的类型修复为'a list
,并按如下方式停用临时重载的“漂亮打印”
declare [[show_variants]]
term "do { m ← oddity (n - 2); (m :: 'a list) }"
结果是
"List.bind (oddity (n - 2)) (λm. m)"
所以你看到的不是分号代码>键入时,将插入一个常量bind
(确切的常量取决于类型)。没有为类型nat
注册bind
,因此出现上述错误。虽然您可以定义某种“身份单子”,但这表明do符号在这里没有多大意义。下面的定义如何
partial_function (tailrec) oddity :: "nat ⇒ nat"
where
"oddity n = (
if n = 0 then 0
else if n ≥ 2 then oddity (n - 2)
else undefined)"
更新:为了完整起见,让我们看看如何定义上述标识monad。首先,我们需要一个绑定操作,即一个常量接受一个标识单子,一个函数返回一个标识单子,并将这些参数组合成一个标识单子。第一个也是最简单的想法可能是
definition "bind_id' x f = f x"
这只是函数应用程序的相反顺序。但是,使用此定义,我们稍后将遇到绑定id'
的单调性问题,这将是(tailrec)
所需的。因此,我们使用
definition "bind_id x f = (if x = undefined then undefined else f x)"
这保证了无论何时x
都是bind\u id x f
未定义的,因此是单调的。然后,我们注册这个新常数,用于一元绑定的临时重载,如下所示
adhoc_overloading
Monad_Syntax.bind bind_id
现在还需要证明bind\u id
w.r.t.mono\u tailrec
的单调性,这只是一个练习(只需模仿部分函数中的mono\u选项
已经完成的操作即可)。那么您使用do符号的定义将被接受
您可能不想让oddity 1
未定义。但由于我不确定“古怪”的目的,所以我不能确定
thm
命令在那里做什么?Isar参考手册说它“检索”了定理,但我想这里潜藏着一些副作用。thm
用于查看事实的实际陈述。也就是说,副作用(实际上是唯一的影响)是显示与给定名称对应的事实(位置取决于用户界面)。谢谢。对于3:是的,这是一个局部函数的最小示例,它不是为奇数自然数定义的,因此得名。