使用列表连接的数据类型索引的问题

时间:2015-03-25 16:12:16

标签: agda

我对使用数据类型的定理的形式化存在令人讨厌的问题,该数据类型具有一些其索引具有列表串联的构造函数。当我尝试使用emacs模式进行大小写分割时,Agda会返回以下错误消息:

I'm not sure if there should be a case for the constructor
o-success, because I get stuck when trying to solve the following
unification problems (inferred index ≟ expected index):
  e₁ o e'' , x₁ ++ x'' ++ y₁ ≟ e o e' , x ++ x' ++ y
  suc (n₂ + n'') , x₁ ++ x'' ≟ m' , p''
when checking that the expression ? has type
suc (.n₁ + .n') == .m' × .x ++ .x' == p'

由于代码的行数不止一个,我把它放在以下要点:

https://gist.github.com/rodrigogribeiro/976b3d5cc82c970314c2

任何提示都表示赞赏。

最佳,

1 个答案:

答案 0 :(得分:3)

有类似的question

但是,您希望xs1 ++ xs2 ++ xs3ys1 ++ ys2 ++ ys3统一,但_++_不是构造函数 - 它是一个函数,并且它不是单射的。考虑这个简化的例子:

data Bar {A : Set} : List A -> Set where
  bar : ∀ xs {ys} -> Bar (xs ++ ys)

ex : ∀ {A} {zs : List A} -> Bar zs -> Bar zs -> List A
ex (bar xs) b = {!!}

b的类型为Bar (xs ++ .ys),但b不一定等于bar .xs,因此您无法像这样进行模式匹配。这里有两个Bar,它们具有相同的类型但值不同:

ok : ∃₂ λ (b1 b2 : Bar (tt ∷ [])) -> b1 ≢ b2
ok = bar [] , bar (tt ∷ []) , λ ()

这是因为xs1 ++ xs2 ≡ ys1 ++ ys2一般不会暗示xs1 ≡ ys1 × xs2 ≡ ys2

但是可以推广一个索引。您可以在上面的链接中使用Vitus描述的技术,或者您可以使用这个简单的组合器,它会忘记索引:

generalize : ∀ {α β} {A : Set α} (B : A -> Set β) {x : A} -> B x -> ∃ B
generalize B y = , y

E.g。

ex : ∀ {A} {zs : List A} -> Bar zs -> Bar zs -> List A
ex {A} (bar xs) b with generalize Bar b
... | ._ , bar ys = xs ++ ys

毕竟,你确定你的引理是真的吗?

<强>更新

首先是一些评论。

您的empty案件陈述

empty : forall x -> G :: (emp , x) => (1 , x)

empty解析器解析整个字符串。它应该是

empty : forall x -> G :: (emp , x) => (1 , [])

如文中所述。

您对o-fail1的定义包含此部分:

(n , fail ∷ o)

但是fail会失败,所以它应该是(n , fail ∷ [])。通过这种表示,您可能需要在A上进行可判定的相等来完成引理,并且证明会很脏。用于表示可能失败的东西的干净且惯用的方式是将其包装在Maybe monad中,所以这是我对_::_=>_的定义:

data _::_=>_ {n} (G : Con n) : Foo n × List A -> Nat × Maybe (List A) -> Set where
  empty       : ∀ {x}     -> G :: emp   ,  x      => 1 , just []
  sym-success : ∀ {a x}   -> G :: sym a , (a ∷ x) => 1 , just (a ∷ [])
  sym-failure : ∀ {a b x} -> ¬ (a == b) -> G :: sym a , b ∷ x => 1 , nothing
  var         : ∀ {x m o} {v : Fin (suc n)}
              -> G :: lookup v G , x => m , o -> G :: var v , x => suc m , o
  o-success : ∀ {e e' x x' y n n'}
            -> G :: e      , x ++ x' ++ y => n            , just x
            -> G :: e'     ,      x' ++ y => n'           , just x'
            -> G :: e o e' , x ++ x' ++ y => suc (n + n') , just (x ++ x')
  o-fail1   : ∀ {e e' x x' y n}
            -> G :: e      , x ++ x' ++ y => n     , nothing
            -> G :: e o e' , x ++ x' ++ y => suc n , nothing
  o-fail2   : ∀ {e e' x x' y n n'}
            -> G :: e      , x ++ x' ++ y => n            , just x
            -> G :: e'     ,      x' ++ y => n'           , nothing
            -> G :: e o e' , x ++ x' ++ y => suc (n + n') , nothing

以下是lemma

postulate
  cut : ∀ {α} {A : Set α} -> ∀ xs {ys zs : List A} -> xs ++ ys == xs ++ zs -> ys == zs

mutual
  aux : ∀ {n} {G : Con n} {e e' z x x' y n n' m' p'}
      -> z == x ++ x' ++ y
      -> G :: e      , z       => n  , just x
      -> G :: e'     , x' ++ y => n' , just x'
      -> G :: e o e' , z       => m' , p'
      -> suc (n + n') == m' × just (x ++ x') == p'
  aux {x = x} {x'} {n = n} {n'} r pr1 pr2 (o-success {x = x''} pr3 pr4) with x | n | lemma pr1 pr3
  ... | ._ | ._ | refl , refl rewrite cut x'' r with x' | n' | lemma pr2 pr4
  ... | ._ | ._ | refl , refl = refl , refl
  aux ...

  lemma : ∀ {n m m'} {G : Con n} {f x p p'}
        -> G :: f , x => m , p -> G :: f , x => m' , p' -> m == m' × p == p'
  lemma (o-success pr1 pr2)  pr3            = aux refl pr1 pr2 pr3
  lemma ...

证据进行如下:

  1. 我们在辅助函数中推广lemma pr3的类型,如在Vitus&#39;回答。现在可以在pr3上进行模式匹配。
  2. 我们证明,lemma' s pr3中的第一个解析器(pr3中也称为aux)产生与pr1相同的输出。< / LI>
  3. 经过一些重写,我们证明lemma pr3中的第二个解析器(pr4中称为aux)产生的输出与{相同{1}}。
  4. 由于pr2pr1生成相同的输出,而pr3pr2生成相同的输出,pr4o-success pr1 pr2会产生相同的输出,所以我们放o-success pr3 pr4
  5. code。我没有证明refl , reflo-fail1个案,但它们应该相似。

    <强>更新

    样板量可以减少

    1. 修复包含冗余信息的o-fail2个案的定义。
    2. 返回fail而不是Maybe (List A)。如果需要,您可以递归计算此Nat × Maybe (List A)
    3. 使用Nat成语而不是辅助功能。
    4. 我认为没有更简单的解决方案。 code