如何在依赖视图上安排模式匹配?

时间:2015-04-22 00:09:18

标签: dependent-type idris

我已经编写了一些简单类型来查看Vect值:

data SnocVect : Vect n a -> Type where
  SnocNil : SnocVect []
  Snoc : (xs : Vect n a) -> (x : a) -> SnocVect (xs ++ [x])

data Split : (m : Nat) -> Vect n a -> Type where
  MkSplit : (xs : Vect j a) -> (ys : Vect k a) ->
              Split j (xs ++ ys)

现在在我看来完全合理的是,如果我有一个Split分隔矢量的最后一个元素,我应该能够将其转换为SnocVect

splitToSnocVect : .{xs : Vect (S n) a} -> Split n xs ->
    SnocVect xs

不幸的是,我似乎找不到任何方法来实现这个东西。特别是,我没有找到任何办法来让我在Split n xs论证上进行模式匹配,没有它我显然无法获得任何结果。我认为基本问题是我有类型的东西

Split j (ps ++ [p])

由于++不是单射的,我需要运用某种魔法来说服类型检查器,事情才有意义。但我不能理解这一点,以确定。

1 个答案:

答案 0 :(得分:1)

我终于明白了!我认为必须是一种更好的方式,但这样做有效。

vectLengthConv : {auto a : Type} -> m = n ->
                    Vect m a = Vect n a
vectLengthConv prf = rewrite prf in Refl

splitToSnocVect' : .(n : Nat) -> .(xs : Vect m a) ->
              .(m = n+1) -> Split n xs -> SnocVect xs
splitToSnocVect' n (ys ++ zs) prf (MkSplit {k} ys zs) 
     with (vectLengthConv (plusLeftCancel n k 1 prf))

  splitToSnocVect' n (ys ++ []) prf
      (MkSplit {k = Z} ys []) | Refl impossible

  splitToSnocVect' n (ys ++ (z :: [])) prf 
     (MkSplit {k = (S Z)} ys (z :: [])) | lenconv =
        Snoc ys z

  splitToSnocVect' n (ys ++ zs) prf 
    (MkSplit {k = (S (S k))} ys zs) | Refl impossible

splitToSnocVect : .{n : Nat} -> .{xs : Vect (S n) a} ->
                       Split n xs -> SnocVect xs
splitToSnocVect {n} {xs} splt =
    splitToSnocVect' n xs (plusCommutative 1 n) splt

修改

David Christiansen建议使用vectLengthConv nixing,而在cong {f=\len=>Vect len a} (plusLeftCancel n k 1 prf)子句中使用with。这有点帮助。