.. package:gdp

Given a value and a proof, attach the proof as a ghost proof on the value.
Apply an implication to the ghost proof attached to a value, leaving the value unchanged.
Take a simple function with one named argument and a named return, plus an implication relating a precondition to a postcondition of the function, and produce a function between refined input and output types.
newtype NonEmpty xs = NonEmpty Defn
type role Nonempty nominal -- disallows coercion of Nonempty's argument.

newtype Reverse  xs = Reverse  Defn
type role Reverse nominal

rev :: ([a] ~~ xs) -> ([a] ~~ Reverse xs)
rev xs = defn (reverse (the xs))

rev_nonempty_lemma :: NonEmpty xs -> Proof (NonEmpty (Reverse xs))

rev' :: ([a] ?NonEmpty) -> ([a] ?NonEmpty)
rev' = rev ...? rev_nonempty_lemma