Voglio tradurre il seguente codice Haskell in Agda:Come implementare l'algoritmo Hare e Tortoise di Floyd in Agda?
import Control.Arrow (first)
import Control.Monad (join)
safeTail :: [a] -> [a]
safeTail [] = []
safeTail (_:xs) = xs
floyd :: [a] -> [a] -> ([a], [a])
floyd xs [] = ([], xs)
floyd (x:xs) (_:ys) = first (x:) $ floyd xs (safeTail ys)
split :: [a] -> ([a], [a])
split = join floyd
Questo ci permette di dividere in modo efficiente un elenco in due:
split [1,2,3,4,5] = ([1,2,3], [4,5])
split [1,2,3,4,5,6] = ([1,2,3], [4,5,6])
Così, ho provato a convertire questo codice per Agda:
floyd : {A : Set} → List A → List A → List A × List A
floyd xs [] = ([] , xs)
floyd (x :: xs) (_ :: ys) = first (x ::_) (floyd xs (safeTail ys))
L'unico problema è che Agda si lamenta che mi manca il caso di floyd [] (y :: ys)
. Tuttavia, questo caso non dovrebbe mai sorgere. Come posso dimostrare ad Agda che questo caso non dovrebbe mai sorgere?
Ecco un esempio visivo di come funziona questo algoritmo:
+-------------+-------------+
| Tortoise | Hare |
+-------------+-------------+
|^1 2 3 4 5 |^1 2 3 4 5 |
| 1^2 3 4 5 | 1 2^3 4 5 |
| 1 2^3 4 5 | 1 2 3 4^5 |
| 1 2 3^4 5 | 1 2 3 4 5^|
+-------------+-------------+
Ecco un altro esempio:
+---------------+---------------+
| Tortoise | Hare |
+---------------+---------------+
|^1 2 3 4 5 6 |^1 2 3 4 5 6 |
| 1^2 3 4 5 6 | 1 2^3 4 5 6 |
| 1 2^3 4 5 6 | 1 2 3 4^5 6 |
| 1 2 3^4 5 6 | 1 2 3 4 5 6^|
+---------------+---------------+
Quando la lepre (il secondo argomento di floyd
) raggiunge la fine della elenco, la tartaruga (il primo argomento a floyd
) raggiunge il centro dell'elenco. Pertanto, utilizzando due puntatori (il secondo si muove due volte più velocemente del primo) possiamo dividere in modo efficiente una lista in due.
[Perché] (http://ideone.com/aKcgNZ) l'accumulatore? – user3237465
@ user3237465 Per un'efficiente ricorsione della coda. Ad ogni modo, non fa alcuna differenza per il problema reale. –
Questo caso 'floyd acc [] (y ∷ ys)' può sorgere, semplicemente chiamando direttamente quella funzione. Potresti dargli un'implementazione fittizia. –