Ответ 1
Я думаю, что основная проблема с вашими доказательствами заключается в том, что, как заметил в комментарии Cactus, у вас нет свойств, таких как транзитивность и антисимметрия, которые необходимы для доказательства сортировки вставки. Тем не менее, вы все равно можете создать полиморфный контейнер: класс Poset из Decidable.Order в contrib содержит именно те свойства, которые вы хотите. Тем не менее, Decidable.Order.Order лучше в этом случае, поскольку он инкапсулирует совокупность отношения, гарантируя, что для любых двух элементов мы можем получить доказательство того, что один из них меньше.
У меня есть другой алгоритм сортировки вставки, в котором я работал в любом случае, который использует Order; он также явно разлагает распределение между списками Empty
и NonEmpty
и сохраняет max
(наибольший элемент, который теперь может быть добавлен в список) в типе списков NonEmpty
, что несколько упрощает доказательства.
Я также изучаю Идрис, поэтому этот код не может быть самым идиоматическим; также большое спасибо Melvar и {AS} на IRC-канале #idris Freenode за то, что помогли мне разобраться, почему предыдущие версии не работали.
Сильный синтаксис with (y) | <pattern matches on y>
в sinsert
существует, чтобы связать y
для assert_smaller
, так как по какой-то причине [email protected](NonEmpty xs)
не работает.
Я надеюсь, что это будет полезно!
import Data.So
import Decidable.Order
%default total
data NonEmptySortedList : (a : Type)
-> (po : a -> a -> Type)
-> (max : a)
-> Type where
SOne : (el : a) -> NonEmptySortedList a po el
SMany : (el : a)
-> po el max
-> NonEmptySortedList a po max
-> NonEmptySortedList a po el
data SortedList : (a : Type) -> (po : a -> a -> Type) -> Type where
Empty : SortedList _ _
NonEmpty : NonEmptySortedList a po _ -> SortedList a po
head : NonEmptySortedList a _ _ -> a
head (SOne a) = a
head (SMany a _ _) = a
tail : NonEmptySortedList a po _ -> SortedList a po
tail (SOne _) = Empty
tail (SMany _ _ xs) = NonEmpty xs
max : {m : a} -> NonEmptySortedList a _ m -> a
max {m} _ = m
newMax : (Ordered a po) => SortedList a po -> a -> a
newMax Empty x = x
newMax (NonEmpty xs) x = either (const x)
(const (max xs))
(order {to = po} x (max xs))
either' : {P : Either a b -> Type}
-> (f : (l : a) -> P (Left l))
-> (g : (r : b) -> P (Right r))
-> (e : Either a b) -> P e
either' f g (Left l) = f l
either' f g (Right r) = g r
sinsert : (Ordered a po)
=> (x : a)
-> (xs : SortedList a po)
-> NonEmptySortedList a po (newMax xs x)
sinsert x y with (y)
| Empty = SOne {po = po} x
| (NonEmpty xs) = either' { P = NonEmptySortedList a po
. either (const x) (const (max xs))
}
insHead
insTail
(order {to = po} x (max xs))
where insHead : po x (max xs) -> NonEmptySortedList a po x
insHead p = SMany x p xs
max_lt_newmax : po (max xs) x -> po (max xs) (newMax (tail xs) x)
max_lt_newmax max_xs_lt_x with (xs)
| (SOne _) = max_xs_lt_x
| (SMany _ max_xs_lt_max_xxs xxs)
= either' { P = po (max xs) . either (const x)
(const (max xxs))}
(const {a = po (max xs) x} max_xs_lt_x)
(const {a = po (max xs) (max xxs)} max_xs_lt_max_xxs)
(order {to = po} x (max xxs))
insTail : po (max xs) x -> NonEmptySortedList a po (max xs)
insTail p = SMany (max xs)
(max_lt_newmax p)
(sinsert x (assert_smaller y (tail xs)))
insSort : (Ordered a po) => List a -> SortedList a po
insSort = foldl (\xs, x => NonEmpty (sinsert x xs)) Empty