Я хочу перевести следующий код 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
Это позволяет нам эффективно разделить список на два:
split [1,2,3,4,5] = ([1,2,3], [4,5])
split [1,2,3,4,5,6] = ([1,2,3], [4,5,6])
Итак, я попытался преобразовать этот код в 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))
Единственная проблема в том, что Агда жалуется, что мне не хватает случая для floyd [] (y :: ys)
. Однако такого случая возникнуть не должно. Как я могу доказать Агде, что такого случая никогда не должно возникнуть?
Вот наглядный пример того, как работает этот алгоритм:
+-------------+-------------+
| 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 ^ |
+-------------+-------------+
Вот еще один пример:
+---------------+---------------+
| 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 ^ |
+---------------+---------------+
Когда заяц (второй аргумент для floyd
) достигает конца списка, черепаха (первый аргумент для floyd
) достигает середины списка. Таким образом, используя два указателя (второй движется вдвое быстрее, чем первый), мы можем эффективно разделить список на два.
floyd acc [] (y ∷ ys)
случай может возникнуть, просто вызвав эту функцию напрямую. Вы можете создать фиктивную реализацию. - person Twan van Laarhoven   schedule 17.02.2016floyd
напрямую. Однако мы не должны этого делать. Тип Haskell для функцииfloyd
слишком разрешительный. Я надеялся, что мы сможем датьfloyd
более строгий шрифт в Agda. Может, зависимый тип? - person Aadit M Shah   schedule 17.02.2016map
,_++_
и другие, использующие хвостовую рекурсию, особенно в параметрах с зависимой типизацией. - person user3237465   schedule 17.02.2016floyd : {A : Set} → List A → (xs : List A) → (ys : List A) → length xs ≥ length ys → List A × List A
. - person Twan van Laarhoven   schedule 17.02.2016map
и т. Д. - person Aadit M Shah   schedule 17.02.2016∀ {n A} → (xs : Vec A n) → Σ left ∶ Vec A ⌈ n /2⌉ • Σ right ∶ Vec A ⌊ n /2 ⌋ • xs ≡ left ++ right
где я пишуΣ x ∶ X • Y
для зависимого продукта вместо неуклюжегоData.Product
Σ[ x ∈ A] Y
--- eww похоже на теорию множеств! --- а свойства потолка / пола можно найти вData.Nat.Properties
. Конечно, как заметят другие, разделение проблем может быть уместным. Если доказательства выходят из-под контроля, можно сформировать операцию, а затем доказать, что она удовлетворяет спецификации. - person Musa Al-hassy   schedule 17.02.2016