coq 基础:bin_to_nat 函数
coq Basics: bin_to_nat function
我正在通过逻辑基础课程,但在基础的最后一个练习题上卡住了:
将二进制数写入其一元表示形式的转换器:
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);
您的代码和 Coq 代码之间的主要区别是 Coq 代码应该 return 自然数,而不是打印它。这意味着我们需要同时跟踪您的解决方案打印的所有内容和 return 结果。
由于打印 S
意味着答案是打印的任何其他内容的后继,我们需要一个函数来获取自然数的第 2^(n) 个后继。有多种方法可以做到这一点,但我建议对 n 进行递归,并指出 x 的第 2^(n + 1) 个后继是第 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);
可以写成(在伪 Coq 中)
pow2_succ i (rec_converter str (S i)).
但是,还有一点需要注意:您可能无法直接访问输入的第 i 个 "character",但这应该不是问题。当您将函数编写为 Fixpoint
Fixpoint rec_converter (n: bin) (i: nat): nat :=
match n with
| Z => 0
| A m => ...
| B m => ...
end.
m 的第一个 "character" 将是原始输入的第二个 "character"。所以你只需要访问第一个 "character",这正是 Fixpoint
所做的。
关于 2 的计算能力的问题,您应该查看 Coq 库中提供的以下文件(至少达到 8.9 版本):
https://coq.inria.fr/distrib/current/stdlib/Coq.Init.Nat.html
此文件包含大量与自然数相关的函数,它们都可以用作说明如何使用 Coq 和此数据类型进行编程。
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's 2004. P167-P168。 (如何理解 'positive' Coq 中的类型)
我正在通过逻辑基础课程,但在基础的最后一个练习题上卡住了:
将二进制数写入其一元表示形式的转换器:
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);
您的代码和 Coq 代码之间的主要区别是 Coq 代码应该 return 自然数,而不是打印它。这意味着我们需要同时跟踪您的解决方案打印的所有内容和 return 结果。
由于打印 S
意味着答案是打印的任何其他内容的后继,我们需要一个函数来获取自然数的第 2^(n) 个后继。有多种方法可以做到这一点,但我建议对 n 进行递归,并指出 x 的第 2^(n + 1) 个后继是第 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);
可以写成(在伪 Coq 中)
pow2_succ i (rec_converter str (S i)).
但是,还有一点需要注意:您可能无法直接访问输入的第 i 个 "character",但这应该不是问题。当您将函数编写为 Fixpoint
Fixpoint rec_converter (n: bin) (i: nat): nat :=
match n with
| Z => 0
| A m => ...
| B m => ...
end.
m 的第一个 "character" 将是原始输入的第二个 "character"。所以你只需要访问第一个 "character",这正是 Fixpoint
所做的。
关于 2 的计算能力的问题,您应该查看 Coq 库中提供的以下文件(至少达到 8.9 版本):
https://coq.inria.fr/distrib/current/stdlib/Coq.Init.Nat.html
此文件包含大量与自然数相关的函数,它们都可以用作说明如何使用 Coq 和此数据类型进行编程。
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's 2004. P167-P168。 (如何理解 'positive' Coq 中的类型)