Sto usando questo tipo di ragionare sulle stringhe su cui l'analisi decidibile può essere eseguita:Generazione di eseguire prove di tempo con il tipo di predicati a Idris
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)
Per esempio, la definizione delle cifre [0-9] come questo:
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
allora possiamo avere le seguenti funzioni:
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)
QuestoLa funzione 0 ora funzionerà bene al momento della compilazione, ma non è molto utile in sé. Per utilizzarlo in fase di esecuzione, è necessario costruire la prova Every Digit (unpack s)
prima di poter utilizzare la funzione.
Quindi penso che ora voglio scrivere qualcosa di simile a questa funzione:
every : (p : a -> Type) -> (xs : List a) -> Maybe $ Every p xs
Che o vogliamo tornare sia una prova di composizione o una prova della non-appartenenza, ma non sono del tutto sicuro come fare entrambe queste cose in modo generale. Così, invece Ho provato a fare la versione Maybe
solo per i personaggi:
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
Ma poi ho ottenere questo errore unificazione:
Can't unify
Type
with
p '0'
Specifically:
Can't unify
Type
with
p '0'
Ma p
è di tipo Char -> Type
. Non sono sicuro di cosa stia causando questo errore di unificazione, ma penso che il problema potrebbe essere correlato a my previous question.
È un approccio ragionevole a quello che sto cercando di fare? Mi sembra che al momento sia un po 'troppo impegnativo, e dovrebbero essere possibili versioni più generali di queste funzioni. Sarebbe bello se la parola chiave auto
potesse essere usata per scrivere una funzione che ti dia un Maybe proof
o un Either proof proofThatItIsNot
, in modo simile a come funziona la classe DecEq
.
Non dovresti usare 'fmap (p '0': :) (ogni p xs)' invece di 'Just $ p '0' ::! (Ogni p xs)'? – is7s
Questo è lo stile migliore, certamente, grazie per il suggerimento (stavo scrivendo il codice abbastanza rapidamente). Per Idris è necessaria una coppia extra di parenti: 'map ((p '0'): :) (ogni p xs)'. (Non anche 'fmap' è solo' map' in Idris). Tuttavia, non cambia l'errore. –