Некоторое время я ломал голову над этой проблемой: у меня есть типы записей с зависимыми полями, и я хочу доказать равенство при преобразованиях записей. Я попытался выразить суть моей проблемы в небольшом примере. Рассмотрим следующий тип записи Rec
, который имеет зависимость между полями:
module Bar where
open import Data.Nat
open import Relation.Binary.PropositionalEquality as PE
open import Relation.Binary.HeterogeneousEquality as HE
record Rec : Set where
field val : ℕ
inc : {n : ℕ} -> ℕ
succ : inc {0} ≡ val
open Rec
Свойство succ
устанавливает связь между двумя другими полями: это inc {0}
возвращает val
. Следующая функция incR
определяет Rec
преобразователь, увеличивающий значение и инкрементор на фиксированное значение m
, сохраняющий их взаимодействие:
succPrf : {x : Rec} {m : ℕ} -> (inc x {0} + m) ≡ val x + m
succPrf {x} {m} rewrite (PE.cong (\x -> x + m) (succ x)) = refl
incR : Rec -> ℕ -> Rec
incR x m = record {
val = val x + m
; inc = λ{n} -> inc x {n} + m
; succ = succPrf {x} {m} }
Здесь succPrf
дает доказательство того, что соотношение _11 _ / _ 12_ выполняется.
Теперь я хочу доказать следующее:
incR0 : forall {x : Rec} -> incR x 0 ≡ x
incR0 {x} = {!!}
Однако это оказывается довольно трудным из-за зависимости внутри записей.
Я попытался разбить его на индивидуальные равенства на полях с целью использования сравнения, чтобы собрать все вместе: и, похоже, я могу уйти довольно далеко:
postulate
ext : {A : Set} {B : Set}
{f g : {a : A} -> B} ->
(forall {n : A} -> f {n} ≡ g {n})
-> (λ {n : A} -> f {n}) ≡ (λ {n : A} -> g {n})
-- Trivial, but for tersity just postulated
runit : {n : ℕ} -> n + 0 ≡ n
incRVal : forall {x : Rec} -> val (incR x 0) ≡ val x
incRVal {x} rewrite runit {val x} = refl
incRinc : forall {x : Rec} -> (λ{n : ℕ} -> inc (incR x 0) {n}) ≡ (λ{n : ℕ} -> inc x {n})
incRinc {x} rewrite ext (λ{n : ℕ} -> runit {inc x {n}}) = refl
А в поле succ
мы должны прибегнуть к гетерогенному равенству
succIncR : {x : Rec} -> (inc (incR x 0) {0} ≡ val (incR x 0) + 0)
≡ (inc x {0} ≡ val x)
succIncR {x} rewrite runit {inc x {0}} | runit {val x} | incRVal {x}
= refl
incRsucc : forall {x : Rec} -> succ (incR x 0) ≅ succ x
incRsucc {x} rewrite succIncR {x} | succ x | runit {val x}
= HE.reflexive refl
Но я изо всех сил пытаюсь совместить их должным образом. Мне действительно нужно какое-то соответствие для Pi-типов, чтобы я мог соединить incRinc
и incRsucc
вместе за один раз, но мне не удалось это построить. Я нахожусь в точке, где я не вижу леса за деревьями, так что хотя бы я мог видеть то, что ТАК думал. Я здесь упускаю какую-то простую технику?