我尝试使用partial_function
关键字定义部分函数。那没起效。这是最能表达直觉的那个:
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 })"
他们都没有奏效。我想我的尝试有概念和句法问题,这些是什么?
答案 0 :(得分:5)
您的定义存在两个问题:
partial_function
不支持左侧的模式匹配。必须使用右侧的case
表达式进行模拟。
类型nat
的构造函数是Suc
和0
,而不是Succ
和Zero
。这就是为什么你的case表达式生成Succ
和Zero
不是数据类型构造函数的错误,以及为什么parital_function
抱怨Zero
是右边的额外变量。
总之,以下工作:
partial_function (tailrec) oddity :: "nat => nat"
where "oddity arg = (case arg of (Suc (Suc n)) => n | 0 => 0 )"
您可以使用simp_of_case
的{{1}}转换来恢复带模式匹配的简化规则:
~~/src/HOL/Library/Simps_Case_Conv
答案 1 :(得分:3)
关于你上一个例子的一些评论:
Isabelle / HOL中没有if-then
没有else
。因此语法错误。要解决此问题,您必须为上一个else
提供if
- 分支,或者重写定义。 E.g。
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)"
此时会出现“未解决的adhoc重载”错误。请记住,do-notation只是语法糖。让我们通过用
查看do-block来试着看看实际发生了什么term "do { m ← oddity (n - 2); m }"
由于仍有未解决的重载问题,我们可以将m
的类型修改为'a list
,并停用adhoc重载的“漂亮打印”,如下所示
declare [[show_variants]]
term "do { m ← oddity (n - 2); (m :: 'a list) }"
结果是
"List.bind (oddity (n - 2)) (λm. m)"
因此,您可以看到,而不是您键入的分号;
,会插入一个常量bind
(确切的常量取决于类型)。没有bind
注册类型nat
,因此出现上述错误。虽然你可以定义某种“身份monad”,但这显示了在这里没有多少意义。相反,以下定义怎么样?
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。首先,我们需要一个绑定操作,即一个常量取一个标识monad和一个返回一个标识monad的函数,并将这些参数组合成一个标识monad。第一个也是最简单的想法可能是
definition "bind_id' x f = f x"
这只是功能应用程序的逆序。但是,根据此定义,我们稍后会遇到bind_id'
所需的(tailrec)
单调性问题。因此我们改为使用
definition "bind_id x f = (if x = undefined then undefined else f x)"
保证bind_id x f
只要undefined
为x
,因此是单调的。然后我们为monadic bind的adhoc重载注册这个新的常量,如此
adhoc_overloading
Monad_Syntax.bind bind_id
现在仍然需要证明bind_id
w.r.t的单调性。 mono_tailrec
,留作练习(只是模仿mono_option
中Partial_Function
已经完成的操作。然后,您接受使用do-notation的定义。
您可能不会oddity 1
未定义。但由于我不确定oddity
的目的,我无法确定。