coq基础知识:bin_to_nat函数

时间:2019-01-19 21:02:10

标签: coq logical-foundations

我正在通过逻辑基础课程,并陷入了基础知识的最后摘要:

具有二进制数,将转换器写入其一元表示形式:

Inductive bin : Type :=
  | Z
  | A (n : bin)
  | B (n : bin).

Fixpoint bin_to_nat (m:bin) : nat :=
  (* What to do here? *)

我用C中的递归函数解决了这个问题。唯一的事情是,我使用“ 0”代替“ A”,而不是“ 1”代替“ B”。

#include <stdio.h>

unsigned int pow2(unsigned int power)
{
    if(power != 0)
        return 2 << (power - 1);
    else
        return 1;
}

void rec_converter(char str[], size_t i)
{
    if(str[i] == 'Z')
        printf("%c", 'Z');
    else if(str[i] == '0')
        rec_converter(str, ++i);
    else if(str[i] == '1')
    {
        unsigned int n = pow2(i);

        for (size_t j = 0; j < n; j++)
        {
            printf("%c", 'S');
        }
        rec_converter(str, ++i);
    }
}

int main(void)
{
    char str[] = "11Z";

    rec_converter(str, 0);
    printf("\n");

    return 0;
}

我现在的问题是如何在coq中编写此代码:

unsigned int n = pow2(i);

for (size_t j = 0; j < n; j++)
{
    printf("%c", 'S');
}
rec_converter(str, ++i);

3 个答案:

答案 0 :(得分:4)

您的代码与Coq代码之间的主要区别在于,Coq代码应该返回自然数,而不是打印自然数。这意味着我们需要跟踪解决方案打印的所有内容,并一次返回所有结果。

由于打印S意味着答案是打印其他任何内容的后继者,因此我们需要一个函数,该函数可以接受自然数的第2 ^(n)个后继者。有多种方法可以执行此操作,但是我建议对n进行递归,并注意x的第2 ^(n + 1)个后继者是x的第2 ^(n)个继任者的第2 ^(n)个继任者。 x。

那应该足以满足您的需求。

unsigned int n = pow2(i);

for (size_t j = 0; j < n; j++)
{
    printf("%c", 'S');
}
rec_converter(str, ++i);

可以写为(pseudo-Coq)

pow2_succ i (rec_converter str (S i)).

但是,还有另一件事要注意:您可能无法直接访问输入的第i个“字符”,但这应该不是问题。当您将函数编写为Fixpoint

Fixpoint rec_converter (n: bin) (i: nat): nat :=
match n with
| Z => 0
| A m => ...
| B m => ...
end.

m的第一个“字符”将是原始输入的第二个“字符”。因此,您只需要访问第一个“字符”,这正是Fixpoint的作用。

答案 1 :(得分:2)

对于2的计算能力问题,您应该查看Coq库中提供的以下文件(至少在8.9版之前):

https://coq.inria.fr/distrib/current/stdlib/Coq.Init.Nat.html

此文件包含许多围绕自然数的函数,它们都可以用作说明如何使用Coq和此数据类型进行编程的例子。

答案 2 :(得分:0)

Fixpoint bin_to_nat (m:bin) : nat :=
  match m with
  | Z => O
  | A n =>2 * (bin_to_nat n)
  | B n =>2 * (bin_to_nat n) + 1
  end.
参见:coq art's2004。P167-P168。 (如何理解Coq中的“阳性”类型)