Оператор match
, который вы пытались написать, на самом деле просто затеняет переменную v
новой переменной, также называемой v
, которая содержит только копию h
.
.два натуральных числа равны, вы можете использовать Nat.eqb
, который возвращает значение bool
, с которым затем можно сопоставить:
Require Import Arith.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => match Nat.eqb v h with
| true => 1 + (count v tl)
| false => count v tl
end
end.
Как это происходит, для сопоставления значений bool
с true
или false
, Coq также предоставляет синтаксический сахар в форме функциональной конструкции if
/ else
(которая очень похожа на троичный оператор ?:
из C или C ++, если вы знакомы с любым из них):
Require Import Arith.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => 0
| h :: tl => if Nat.eqb v h then
1 + (count v tl)
else
count v tl
end.
(На самом деле, бывает, что if
работает с любым индуктивным типом точно с двумя конструкторами: тогда первый конструктор переходит в ветку if
, а второй конструктор - в ветку else
Однако тип list
имеет nil
в качестве первого конструктора и cons
в качестве второго конструктора: так что даже если технически можно написать оператор if
, взяв list
для проверкит для пустоты или незаполненности, это в конечном итоге перевернуло бы то, как вы, вероятно, ожидаете, что это сработает.)
В общем, однако, для универсального типа не обязательно будет способ решить, являются ли двачлены этого типа равны или нет, как было Nat.eqb
в случае nat
.Поэтому, если вы хотите написать обобщение count
, которое могло бы работать для более общих типов, вам нужно было бы принять аргумент, определяющий процедуру принятия решения о равенстве.