[英]How to implement Floyd's Hare and Tortoise algorithm in Agda?
I want to translate the following Haskell code into Agda: 我想将以下Haskell代码转换为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
This allows us to efficiently split a list into two: 这使我们能够有效地将列表拆分为两个:
split [1,2,3,4,5] = ([1,2,3], [4,5])
split [1,2,3,4,5,6] = ([1,2,3], [4,5,6])
So, I tried to convert this code to Agda: 所以,我试图将此代码转换为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))
The only problem is that Agda complains that I'm missing the case for floyd [] (y :: ys)
. 唯一的问题是Agda抱怨我错过了floyd [] (y :: ys)
。 However, this case should never arise. 但是,这种情况永远不应该出现。 How can I prove to Agda that this case should never arise? 我怎样才能向Agda证明这种情况永远不会出现?
Here's a visual example of how this algorithm works: 以下是此算法如何工作的可视示例:
+-------------+-------------+
| 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 ^ |
+-------------+-------------+
Here's another example: 这是另一个例子:
+---------------+---------------+
| 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 ^ |
+---------------+---------------+
When the hare (the second argument to floyd
) reaches the end of the list, the tortoise (the first argument to floyd
) reaches the middle of the list. 当野兔( floyd
的第二个参数)到达列表的末尾时,乌龟( floyd
的第一个参数)到达列表的中间位置。 Thus, by using two pointers (the second one moving twice as fast as the first) we can efficiently split a list into two. 因此,通过使用两个指针(第二个指针移动速度是第一个指针的两倍),我们可以有效地将列表拆分为两个。
The same thing as Twan van Laarhoven suggests in the comments but with Vec
s. 和Twan van Laarhoven在评论中提出的建议相同,但是对于Vec
。 His version is probably better. 他的版本可能更好。
open import Function
open import Data.Nat.Base
open import Data.Product renaming (map to pmap)
open import Data.List.Base
open import Data.Vec hiding (split)
≤-step : ∀ {m n} -> m ≤ n -> m ≤ suc n
≤-step z≤n = z≤n
≤-step (s≤s le) = s≤s (≤-step le)
≤-refl : ∀ {n} -> n ≤ n
≤-refl {0} = z≤n
≤-refl {suc n} = s≤s ≤-refl
floyd : ∀ {A : Set} {n m} -> m ≤ n -> Vec A n -> Vec A m -> List A × List A
floyd z≤n xs [] = [] , toList xs
floyd (s≤s z≤n) (x ∷ xs) (y ∷ []) = x ∷ [] , toList xs
floyd (s≤s (s≤s le)) (x ∷ xs) (y ∷ z ∷ ys) = pmap (x ∷_) id (floyd (≤-step le) xs ys)
split : ∀ {A : Set} -> List A -> List A × List A
split xs = floyd ≤-refl (fromList xs) (fromList xs)
open import Relation.Binary.PropositionalEquality
test₁ : split (1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ []) ≡ (1 ∷ 2 ∷ 3 ∷ [] , 4 ∷ 5 ∷ [])
test₁ = refl
test₂ : split (1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ 6 ∷ []) ≡ (1 ∷ 2 ∷ 3 ∷ [] , 4 ∷ 5 ∷ 6 ∷ [])
test₂ = refl
Also, functions like ≤-refl
and ≤-step
are somewhere in the standard library, but I was lazy to search. 此外,像≤-refl
和≤-step
这样的函数在标准库中的某处,但我懒得搜索。
Here is a silly thing I like to do: 这是我喜欢做的傻事:
open import Function
open import Data.Nat.Base
open import Data.Product renaming (map to pmap)
open import Data.List.Base
open import Data.Vec hiding (split)
floyd : ∀ {A : Set}
-> (k : ℕ -> ℕ)
-> (∀ {n} -> Vec A (k (suc n)) -> Vec A (suc (k n)))
-> ∀ n
-> Vec A (k n)
-> List A × List A
floyd k u 0 xs = [] , toList xs
floyd k u 1 xs with u xs
... | x ∷ xs' = x ∷ [] , toList xs'
floyd k u (suc (suc n)) xs with u xs
... | x ∷ xs' = pmap (x ∷_) id (floyd (k ∘ suc) u n xs')
split : ∀ {A : Set} -> List A -> List A × List A
split xs = floyd id id (length xs) (fromList xs)
open import Relation.Binary.PropositionalEquality
test₁ : split (1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ []) ≡ (1 ∷ 2 ∷ 3 ∷ [] , 4 ∷ 5 ∷ [])
test₁ = refl
test₂ : split (1 ∷ 2 ∷ 3 ∷ 4 ∷ 5 ∷ 6 ∷ []) ≡ (1 ∷ 2 ∷ 3 ∷ [] , 4 ∷ 5 ∷ 6 ∷ [])
test₂ = refl
This is partly based on the Benjamin Hodgson suggestion in the comment below. 这部分是基于下面评论中的Benjamin Hodgson建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.