Having done exercise 9.1 of the book Type Driven Development with Idris I can not get one of my proofs to be complete. The exercise is to make the isLast
function work. It should return a proof of that a value is the last value of a List
. It works, but unfortunately notLastInTailEqNotLast
is not total.
data Last : List a -> a -> Type where
LastOne : Last [value] value
LastCons : (prf : Last xs value) -> Last (x :: xs) value
lastNotNil : Last [] value -> Void
lastNotNil _ impossible
lastNotEq : (contra : (lastValue = value) -> Void) -> Last [lastValue] value -> Void
lastNotEq contra LastOne = contra Refl
lastNotEq _ (LastCons LastOne) impossible
lastNotEq _ (LastCons (LastCons _)) impossible
notLastInTailEqNotLast : (notLastInTail : Last xs value -> Void) ->
Last (y :: xs) value -> Void
notLastInTailEqNotLast notLastInTail LastOne = ?hole
notLastInTailEqNotLast notLastInTail (LastCons prf) = notLastInTail prf
isLast : DecEq a => (xs : List a) -> (value : a) -> Dec (Last xs value)
isLast [] value = No lastNotNil
isLast [lastValue] value = case decEq lastValue value of
Yes Refl => Yes LastOne
No contra => No (lastNotEq contra)
isLast (x :: xs) value = case isLast xs value of
Yes last => Yes (LastCons last)
No notLastInTail => No (notLastInTailEqNotLast notLastInTail)
How can I fill ?hole
?
I have seen the solution here: https://github.com/edwinb/TypeDD-Samples/blob/master/Chapter9/Exercises/ex_9_1.idr. I understand how that works around my problem using lastNotCons
and I can my solution to work that way, but it seems like a workaround. The proof I want to provide seems trivial to me: if I have proof that an element is not the last element in a list then another list with that list appended will still not have that element as the last element in the list (i.e. notLastInTailEqNotLast
).
Help is much appreciated.