Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Isabelle中定义部分函数?_Isabelle - Fatal编程技术网

如何在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:是的,这是一个局部函数的最小示例,它不是为奇数自然数定义的,因此得名。