類型謂詞生成運行時證明我使用此類型推理可以在其上進行可判定的解析字符串:與伊德里斯
data Every : (a -> Type) -> List a -> Type where
Nil : {P : a -> Type} -> Every P []
(::) : {P : a -> Type} -> P x -> Every P xs -> Every P (x::xs)
例如,定義數字[0-9]所示:
data Digit : Char -> Type where
Zero : Digit '0'
One : Digit '1'
Two : Digit '2'
Three : Digit '3'
Four : Digit '4'
Five : Digit '5'
Six : Digit '6'
Seven : Digit '7'
Eight : Digit '8'
Nine : Digit '9'
digitToNat : Digit a -> Nat
digitToNat Zero = 0
digitToNat One = 1
digitToNat Two = 2
digitToNat Three = 3
digitToNat Four = 4
digitToNat Five = 5
digitToNat Six = 6
digitToNat Seven = 7
digitToNat Eight = 8
digitToNat Nine = 9
那麼我們可以有以下功能:
fromDigits : Every Digit xs -> Nat -> Nat
fromDigits [] k = 0
fromDigits (x :: xs) k = (digitToNat x) * (pow 10 k) + fromDigits xs (k-1)
s2n : (s : String) -> {auto p : Every Digit (unpack s)} -> Nat
s2n {p} s = fromDigits p (length s - 1)
這s2n
函數現在可以在編譯時正常工作,但是它本身並不是很有用。要在運行時使用它,我們必須構造證明Every Digit (unpack s)
,然後才能使用該函數。
所以我覺得我現在想寫這樣的功能:
every : (p : a -> Type) -> (xs : List a) -> Maybe $ Every p xs
這還是我們要返回一個成員資格證明或者非會員的證明,但我不能完全肯定如何以一般方式做這些事情。所以不是我試圖做的Maybe
版本只是字符:
every : (p : Char -> Type) -> (xs : List Char) -> Maybe $ Every p xs
every p [] = Just []
every p (x :: xs) with (decEq x '0')
every p ('0' :: xs) | (Yes Refl) = Just $ p '0' :: !(every p xs)
every p (x :: xs) | (No contra) = Nothing
但後來我得到這個錯誤的統一:
Can't unify
Type
with
p '0'
Specifically:
Can't unify
Type
with
p '0'
但p
是Char -> Type
型。我不確定是什麼導致了統一失敗,但認爲這個問題可能與my previous question有關。
這是一個明智的做法是什麼,我想幹什麼?我覺得目前有很多工作要做,而且這些功能的更一般版本應該是可能的。如果auto
關鍵字可以用來寫一個函數給你一個Maybe proof
或Either proof proofThatItIsNot
,以類似的方式如何DecEq
類作品這將是很好。
你不應該用'FMAP(P '0'::)(每P XS)',而不是'只要$ P '0' ::(每P XS)'!? – is7s 2014-11-24 11:19:24
這是更好的風格,當然,謝謝你的建議(我正在寫代碼很快)。 Idris需要額外的一對parens來接受它:map((p'0'):) :(每p xs)'。 (也不是'fmap'就是Idris中的'map')。 雖然不會更改錯誤。 – 2014-11-24 12:46:18