Je souhaite une fonction find
pour les flux de types liés à la taille, similaire aux fonctions de recherche de listes et de vecteurs.Totalité et recherche d'éléments dans les flux
total
find : MaxBound a => (a -> Bool) -> Stream a -> Maybe a
Le défi est à faire:
- être totale
- ne consomment pas plus
constant espace Nde log_2 où N est le nombre de bits requis pour coder le plus granda
. - pas prendre plus d'une minute pour vérifier au moment de la compilation
- imposer sans frais d'exécution
En général, une mise en œuvre de découverte totale pour les flux semble absurde. Les flux sont infinis et un prédicat de const False
rendrait la recherche éternelle. Une bonne façon de gérer ce cas général est la technique du carburant infini.
data Fuel = Dry | More (Lazy Fuel)
partial
forever : Fuel
forever = More forever
total
find : Fuel -> (a -> Bool) -> Stream a -> Maybe a
find Dry _ _ = Nothing
find (More fuel) f (value :: xs) = if f value
then Just value
else find fuel f xs
qui fonctionne bien pour mon cas d'utilisation, mais je me demande si, dans certains cas spécialisés le vérificateur de la totalité pourrait être convaincu sans utiliser forever
. Sinon, quelqu'un risque de subir une vie ennuyeuse en attendant find forever ?predicateWhichHappensToAlwaysReturnFalse (iterate S Z)
pour finir. Considérons le cas particulier où a
est Bits32
.
find32 : (Bits32 -> Bool) -> Stream Bits32 -> Maybe Bits32
find32 f (value :: xs) = if f value then Just value else find32 f xs
Deux problèmes: ce n'est pas totale et cela ne peut pas revenir Nothing
même si il y a un nombre fini de Bits32
habitants à essayer. Peut-être que je pourrais utiliser take (pow 2 32)
pour créer une liste, puis utiliser la recherche de liste ... euh, attendez ... la liste à elle seule prendrait des Go d'espace.
En principe, cela ne devrait pas être difficile. Il y a un nombre fini d'habitants à essayer, et un ordinateur moderne peut parcourir toutes les permutations 32 bits en quelques secondes. Y at-il un moyen d'avoir le vérificateur de totalité the (Stream Bits32) $ iterate (+1) 0
cycles éventuellement revenir à 0
et une fois qu'il affirme que tous les éléments ont été essayés depuis (+1)
est pur?
Voici un début, même si je ne suis pas sûr de savoir comment remplir les trous et de spécialiser find
assez pour le rendre total. Peut-être qu'une interface aiderait?
total
IsCyclic : (init : a) -> (succ : a -> a) -> Type
data FinStream : Type -> Type where
MkFinStream : (init : a) ->
(succ : a -> a) ->
{prf : IsCyclic init succ} ->
FinStream a
partial
find : Eq a => (a -> Bool) -> FinStream a -> Maybe a
find pred (MkFinStream {prf} init succ) = if pred init
then Just init
else find' (succ init)
where
partial
find' : a -> Maybe a
find' x = if x == init
then Nothing
else
if pred x
then Just x
else find' (succ x)
total
all32bits : FinStream Bits32
all32bits = MkFinStream 0 (+1) {prf=?prf}
est-il un moyen de dire le vérificateur de la totalité d'utiliser du carburant infini vérifier une recherche sur un flux particulier est total?
Can 'isCyclic' et 'find' peuvent-ils être implémentés sans compter sur l'espace linéaire' Nat's? Je n'étais même pas assez patient pour que tout se termine sur ma machine, et je suppose que Nat est le coupable. Un programme C non optimisé qui itère sur tous les 'unsigned int' prend un peu plus de 10 secondes sur ma machine, et je vise des performances comparables avec une consommation d'espace constante. –
Vous avez raison, c'est un problème de longue date. Les nombres binaires peuvent soulager la douleur. Il y a un projet sur github, qui vise à porter les nombres binaires de Coq à Idris. –
Ces nombres binaires sont-ils une définition inductive non optimisée? J'imagine que cela aiderait, mais peut-il être fait en utilisant optimisé arbitraire-précision non signé ints? (Il est vrai que l'une ou l'autre des solutions consommerait $ \ log_2 n $ plutôt qu'un espace constant.) –