使用the standard library中的ℕ
和_≟_
,
open import Data.Nat
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
foo : ℕ -> ℕ -> ℕ
foo x y with x ≟ y
foo x .x | yes refl = x
foo x y | no contra = y
data Bar : ℕ -> Set where
bar : (x : ℕ) -> Bar (foo x x)
我想实施
mkBar : (x : ℕ) -> Bar x
mkBar x = bar x
Agda抱怨,
Type mismatch:
expected: x
actual: foo x x | x ≟ x
when checking that the expression bar x
has type Bar x
这对我来说很有意义:Agda并不知道x ≟ x
始终评估为yes refl
的先验,因此它不会评估foo x x
直到它对x
了解更多。
所以我尝试重写目标,强制x ≟ x
解析为yes refl
,
eq-refl : forall x -> (x ≟ x) ≡ yes refl
eq-refl x with x ≟ x
eq-refl x | yes refl = refl
eq-refl x | no contra = ⊥-elim (contra refl)
mkBar : (x : ℕ) -> Bar x
mkBar x rewrite eq-refl x = bar x
但无济于事。相同的错误消息。我也试过foo x x ≡ x
重写:
foo-eq : forall x -> foo x x ≡ x
foo-eq x rewrite eq-refl x = refl
mkBar : (x : ℕ) -> Bar x
mkBar x rewrite foo-eq x = bar x
This answer建议在x ≟ x
左侧的mkBar
上进行模式匹配,但它似乎也没有效果:
mkBar : (x : ℕ) -> Bar x
mkBar x with x ≟ x
mkBar x | yes refl = bar x
mkBar x | no contra = ⊥-elim (contra refl)
我必须在这里错过一个技巧。如何摆脱目标类型中的|
并将foo x x
缩减为x
? (我不希望直接在x
的LHS中检查mkBar
。)
答案 0 :(得分:3)
你几乎就在那里:需要注意的重要一点是rewrite
需要x ≡ y
并在目标中用x
替换y
。 foo-eq x
的类型为foo x x ≡ x
,但目标中没有foo x x
替换!
您需要做的是按sym (foo-eq x)
重写,如下所示:
mkBar : (x : ℕ) → Bar x
mkBar x rewrite sym (foo-eq x) = bar x
Bar x
然后变为Bar (foo x x)
,这意味着您可以应用构造函数。