使Agda减少目标类型中的表达式

时间:2017-05-15 21:44:58

标签: agda dependent-type theorem-proving

使用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。)

1 个答案:

答案 0 :(得分:3)

你几乎就在那里:需要注意的重要一点是rewrite需要x ≡ y并在目标中用x替换yfoo-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),这意味着您可以应用构造函数。