我如何让 Idris 中的完整性检查器相信我没有使用变量?

How do I convince the totality checker in Idris that I'm not using a variable?

我一直无法让 Idris 完整性检查器相信我的函数是完整的。这是我 运行 遇到的问题的一个简单示例版本。假设我们有一个非常简单的表达式类型,其形式如下:

data SimpleType = Prop | Fn SimpleType SimpleType

data Expr : SimpleType -> Type where
  Var : String -> Expr type
  Lam : String -> Expr rng -> Expr (Fn dom rng)
  App : Expr (Fn dom rng) -> Expr dom -> Expr rng

我想写函数

total sub : {a, b : SimpleType} -> String -> Expr a -> Expr b -> Expr b

SimpleType 需要一个 DecEq 实例,但没什么特别的。问题是如何让类型检查器相信这个函数是完整的。例如,考虑按如下方式实现 sub

total sub : {a, b : SimpleType} -> String -> Expr a -> Expr b -> Expr b
sub name repl (App l r) = App (substitute name repl l) (substitute name repl r)
sub _ _ expr = expr

(这是不正确的,但这是一个很好的起点。)这会产生错误:

Main.sub is possibly not total due to: repl

乍一看,Idris 似乎无法验证 l 和 r 在结构上小于 (App l r)。也许以下方法会起作用?

total sub : {a, b : SimpleType} -> String -> Expr a -> Expr b -> Expr b
sub name repl expr@(App l r) = App
  (sub name repl (assert_smaller expr l))
  (sub name repl (assert_smaller expr r))
sub _ _ expr = expr

不!

Main.sub is possibly not total due to: repl

事实上,经过进一步的调查,可以发现,当这个程序编译时:

total sub : {a, b : SimpleType} -> String -> Expr a -> Expr b -> Expr b
sub _ _ expr = expr

这个没有!

total sub : {a, b : SimpleType} -> String -> Expr a -> Expr b -> Expr b
sub _ repl expr = expr

现在我不知道如何让 Idris 相信,在最后一个例子中,repl 真的不会干扰整体性。有人知道如何进行这项工作吗?

事实证明这是完整性检查器中的一个错误,它认为您在左侧提到的 'repl' 是库中定义的用于制作简单交互循环的那个。显然不是 - 这只是名称查找中的一个错误 - 解决这个问题很简单。

这已在 git 母版中修复,因此将在下一个版本中修复。同时,使用与 'repl' 不同的名称也可以(我知道这有点烦人,但是你去...)