为什么这个'with'块会破坏这个功能的整体性?

时间:2017-10-04 10:01:12

标签: idris termination totality

我正在尝试与自然数字的一半计算平价:

data IsEven : Nat -> Nat -> Type where
    Times2 : (n : Nat) -> IsEven (n + n) n

data IsOdd : Nat -> Nat -> Type where
    Times2Plus1 : (n : Nat) -> IsOdd (S (n + n)) n

parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n))

我尝试使用parity的明显实现:

parity Z = Left $ Evidence _ $ Times2 0
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0
parity (S (S n)) with (parity n)
  parity (S (S (k + k))) | Left (Evidence _ (Times2 k)) =
      Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k)
  parity (S (S (S ((k + k))))) | Right (Evidence _ (Times2Plus1 k)) =
      Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k)

这种类型检查并按预期工作。但是,如果我尝试将parity标记为total,Idris会开始抱怨:

 parity is possibly not total due to: with block in parity

我在with中看到的唯一parity块是从parity (S (S n))parity n的递归调用,但显然是有充分根据的,因为{{ 1}}在结构上小于n

我如何说服伊德里斯S (S n)是完全的?

1 个答案:

答案 0 :(得分:2)

对我来说这看起来像个错误,因为基于case的以下解决方案通过了整体检查程序:

total
parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n))
parity Z = Left $ Evidence _ $ Times2 0
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0
parity (S (S k)) =
  case (parity k) of
    Left (Evidence k (Times2 k)) =>
      Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k)
    Right (Evidence k (Times2Plus1 k)) =>
      Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k)