Ich möchte folgendes Haskell-Code in Agda übersetzen: usWie implementiert man Floyds Hare and Tortoise-Algorithmus 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
Dies ermöglicht es, effizient eine Liste in zwei Teile aufgeteilt:
split [1,2,3,4,5] = ([1,2,3], [4,5])
split [1,2,3,4,5,6] = ([1,2,3], [4,5,6])
Also habe ich versucht, diesen Code zu Agda konvertieren:
Das einzige Problem ist, dass Agda beschwert, dass ich den Fall für vermisse. Dieser Fall sollte jedoch niemals auftreten. Wie kann ich Agda beweisen, dass dieser Fall niemals auftauchen sollte?
Hier ist ein visuelles Beispiel dafür, wie dieser Algorithmus funktioniert:
+-------------+-------------+
| 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^|
+-------------+-------------+
Hier ein weiteres Beispiel:
+---------------+---------------+
| 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^|
+---------------+---------------+
Wenn der Hase (das zweite Argument zu floyd
) das Ende der erreicht Liste, die Schildkröte (das erste Argument zu floyd
) erreicht die Mitte der Liste. Indem wir zwei Zeiger verwenden (der zweite bewegt sich doppelt so schnell wie der erste), können wir eine Liste effizient in zwei teilen.
[Warum] (http://ideone.com/aKcgNZ) der Akku? – user3237465
@ user3237465 Für effiziente Tail-Rekursion. Wie auch immer, es macht für das eigentliche Problem keinen Unterschied. –
Dieser Fall 'floyd acc [] (y ∷ ys) kann auftreten, indem Sie diese Funktion direkt aufrufen. Sie könnten es eine Dummy-Implementierung geben. –