2017-10-04 70 views
2

我試圖計算奇偶校驗與半的地板一起,在自然數:這個'with'塊爲什麼會破壞這個函數的整體性?

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) 

這typechecks和工作原理預期。但是,如果我嘗試標記paritytotal,伊德里斯開始抱怨:

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

唯一with塊我在parity看到的是一個從parity (S (S n))parity n遞歸調用,但顯然是有理有據的,因爲n在結構上比S (S n)小。

我如何說服伊德里斯認爲parity是總數?

+1

我打開[問題#4100](https://github.com/idris-lang/ Idis-dev/issues/4100)在GitHub上。 –

回答

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) 
+0

我可以證實這個解決方法適用於我在原始問題中的問題 - 但在其他情況下,'with'不能總是被重寫爲'case',對吧?我正在考慮模式匹配改善其他參數類型的情況。 – Cactus

+0

對!這裏有一個相關的問題:https://stackoverflow.com/q/35610366/2747511。我們很幸運,我們在上下文中有證據。 –

+0

嗯,那麼,這是否意味着我應該嘗試手動展開這些'帶',看看它是否有效? – Cactus