この型を使用して、決定可能な解析を実行できる文字列について推論しています。
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
。この統合の失敗の原因はわかりませんが、問題は以前の質問に関連している可能性があると思います。
これは私がやろうとしていることに対する賢明なアプローチですか? 現時点では少し多すぎるように感じますが、これらの関数のより一般的なバージョンが可能になるはずです。クラスがどのように機能するかと同様の方法で、キーワードを使用して aまたはauto
を与える関数を記述できるとよいでしょう。Maybe proof
Either proof proofThatItIsNot
DecEq