Idris - 我可以表达模式匹配中两个类型参数相等吗?

时间:2018-01-13 03:41:55

标签: equality idris dependent-type type-parameter

假设我有以下

data Expr : Type -> Type where
  Lift : a -> Expr a
  Add  : Num a => Expr a -> Expr a -> Expr a
  Cnst : Expr a -> Expr b -> Expr a

data Context : Type -> Type where
  Root : Context ()
  L    : Expr w -> Context x -> Expr y -> Expr z -> Context w
  R    : Expr w -> Context x -> Expr y -> Expr z -> Context w 
  M    : Expr w -> Context x -> Expr y -> Expr z -> Context w 

data Zipper : Type -> Type -> Type where
  Z : Expr f -> Context g -> Zipper f g
  E : String -> Context g -> Zipper String ()

如果我在表达式树中上升一级,我想编写一个重建Zipper的函数。类似的东西:

total
ZipUp : Zipper focus parent -> Type
ZipUp (Z e (R (Cnst {a} e1 e2) {x} c t u)) = Zipper a x
ZipUp (Z {f} e (L (Cnst l r) {x} c t u))   = Zipper f x
ZipUp (Z e (R (Add {a} e1 e2) {x} c t u))  = Zipper a x
ZipUp (Z {f} e (L (Add e1 e2) {x} c t u))  = Zipper f x
ZipUp _                                    = Zipper String ()

当我想编写函数以返回ZipUp

时,问题就出现了
up : (x : Zipper focus parent) -> ZipUp x
up (Z e (R (Cnst l r) c x y)) = Z (Cnst l e) c
up (Z e (L (Cnst l r) c x y)) = Z (Cnst e r) c
up (Z e (R (Add l r) c x y))  = Z (Add l e) c
up (Z e (L (Add l r) c x y))  = Z (Add e r) c
up (Z e (R (Lift x) c l r))   = E "Some error" c
up (Z e (L (Lift x) c l r))   = E "Some error" c
up (E s c)                    = E s c 

这无法对Add案例进行类型检查,因为它无法推断focus (type of e)parent (expected type)匹配

所以我的问题有两部分。

我可以做些什么来表达这种关系? (如果Zipper是R构建的,e与[{1}}的类型相同,或r的类型与e相同在l构造的案例中。我已尝试使用L及其他变种,但无济于事。)

代码类型检查并运行,如果我注释掉最后一行{e = l}以完成:

up

但是up : (x : Zipper focus parent) -> ZipUp x up (Z e (R (Cnst l r) c x y)) = Z (Cnst l e) c up (Z e (L (Cnst l r) c x y)) = Z (Cnst e r) c 案例中对类型的实际操作应该是相同的,但这不能进行类型检查,为什么会这样?

感谢您花时间阅读和/或回答!

1 个答案:

答案 0 :(得分:1)

  

这无法对添加案例进行类型检查,因为它无法推断focus (type of e)parent (expected type)匹配

因为情况并非总是如此,例如

*main> :t Z (Lift "a") (R (Add (Lift 1) (Lift 2)) Root (Lift 4) (Lift 8))
Z (Lift "a") (R (Add (Lift 1) (Lift 2)) Root (Lift 4) (Lift 8)) : Zipper String Integer

由于Add (Lift 1) (Lift "a")约束,Num a不起作用。

  

我可以做些什么来表达这种关系?

如果您想在内容中表达关系:您有e : Expr f并且可以说在f案例中应该使用相同的Add

up (Z {f} e (R (Add l r {a=f}) c x y)) = Z (Add l e) c
up (Z {f} e (L (Add l r {a=f}) c x y)) = Z (Add e r) c
up (Z e (R (Add l r) c x y)) = ?whattodo_1
up (Z e (L (Add l r) c x y)) = ?whattodo_2

由于a != f的情况,现在你有一个非全部功能。我不太想你做什么,所以我不能提供选择。 : - )

如果你想在Zipper中表达关系,你可以(非常粗略地)表达:

data Context : Bool -> Type -> Type where
  Root : Context False ()
  L    : Expr w -> Context b x -> Expr y -> Expr z -> Context False w
  R    : Expr w -> Context b x -> Expr y -> Expr z -> Context True w 
  M    : Expr w -> Context b x -> Expr y -> Expr z -> Context False w 

data Zipper : Type -> Type -> Type where
  Z : Expr f -> Context False g -> Zipper f g
  ZR : Expr f -> Context True f -> Zipper f f
  E : String -> Context b g -> Zipper String ()

现在,您可以在R-Context中构建f = g拉链时构建证明。同样,我不能具体,但我希望它在某种程度上有所帮助。