前の回答は素晴らしいですが、読み書きするのは少し退屈です。また、自然数を使用しているため、非常に制限されています。直接整数に移行しないのはなぜですか?
まず、すべての ASCII 文字を整数にマップします。
Require Import ZArith String Ascii.
Open Scope Z_scope.
Definition Z_of_bool (b : bool) := if b then 1 else 0.
(* This coercion is used to make the next function shorter to write and read *)
Coercion Z_of_bool : bool >-> Z.
Definition Z_of_ascii a :=
match a with
Ascii b1 b2 b3 b4 b5 b6 b7 b8 =>
b1 + 2 * (b2 + 2 * (b3 + 2 * (b4 + 2 *
(b5 + 2 * (b6 + 2 * (b7 + 2 * b8))))))
end.
実行する必要があるのは 1 つのケースだけであり、取得した順序で数字が次々ときれいに配置されます (ASCII コードは、Coq が発明されるずっと前にそのように設計されました)。
Definition Z_of_0 := Eval compute in Z_of_ascii "0".
Definition Z_of_digit a :=
let v := Z_of_ascii a - Z_of_0 in
match v ?= 0 with
Lt => None | Eq => Some v |
Gt => match v ?= 10 with Lt => Some v | _ => None end
end.
リストを逆にすることなく、数桁の文字列を処理する別の試みを次に示します。
Fixpoint num_prefix_and_length (s : string) : option (Z * Z) :=
match s with
EmptyString => None
| String a s' =>
match Z_of_digit a with
None => None
| Some va =>
match num_prefix_and_length s' with
None => Some (va, 1)
| Some (vs, n) => Some (va * 10 ^ n + vs, n+1)
end
end
end.
この場合、関数は末尾の文字を含む文字列を受け入れます。
Compute num_prefix_and_length "31415926 remind me of Pi".
Some (31415926, 8) を返します。