I am writing an undergraduate thesis on usefulness of dependent types. I am trying to construct a container, that can only be constructed into a sorted list, so that it is proven sorted by construction:
import Data.So
mutual
data SortedList : (a : Type) -> {ord : Ord a) -> Type where
SNil : SortedList a
SMore : (ord : Ord a) => (el: a) -> (xs : SortedList a) -> So (canPrepend el xs) -> SortedList a
canPrepend : Ord a => a -> SortedList a -> Bool
canPrepend el SNil = True
canPrepend el (SMore x xs prf) = el <= x
SMore
requires a runtime proof that the element being prepended is smaller or equal than the smallest (first) element in the sorted list.
To sort an unsorted list, I have created a function sinsert
that takes a sorted list and inserts an element and returns a sorted list:
sinsert : (ord : Ord a) => SortedList a {ord} -> a -> SortedList a {ord}
sinsert SNil el = SMore el SNil Oh
sinsert (SMore x xs prf) el = either
(\p =>
-- if el <= x we can prepend it directly
SMore el (SMore x xs prf) p
)
(\np =>
-- if not (el <= x) then we have to insert it in the tail somewhere
-- does not (el <= x) imply el > x ???
-- we construct a new tail by inserting el into xs
let (SMore nx nxs nprf) = (sinsert xs el) in
-- we get two cases:
-- 1) el was prepended to xs and is now the
-- smalest element in the new tail
-- we know that el == nx
-- therefor we can substitute el with nx
-- and we get nx > x and this also means
-- x < nx and also x <= nx and we can
-- prepend x to the new tail
-- 2) el was inserted somewhere deeper in the
-- tail. The first element of the new tail
-- nx is the same as it was in the original
-- tail, therefor we can prepend x to the
-- new tail based on the old proof `prf`
either
(\pp =>
SMore x (SMore nx nxs nprf) ?iins21
)
(\npp =>
SMore x (SMore nx nxs nprf) ?iins22
) (choose (el == nx))
) (choose (el <= x))
I am having trouble constructing the proofs (?iins21
, ?iins22
) and I would appreciate some help. I may be relying on an assumption that does not hold, but I do not see it.
I would also like to encourage you to provide a better solution for constructing a sorted list (maybe a normal list with a proof value that it is sorted?)
SortedList
type is too blind to the intricacies of ordering. For example, you can't prove something liketransitivity : Ord a => {x : a} -> So (x <= y) -> So (y <= z) -> So (x <= z)
when theOrd
typeclass doesn't have any proof obligations. – Cactusa
to e.g.Nat
and using propositions likex `LTE` y
instead ofSo (x <= y)
. – Cactus