What are the good examples of programs that are simple to specify as dependent types but complex to implement?


Last year I asked "Dependent types can prove your code is correct up to a specification. But how do you prove the specification is correct?". The most voted answer presents the following reasoning:

The hope is that your specification is simple and small enough to judge by examination, while your implementation of that might be far larger.

That line of reasoning makes sense to me. Idris is the most accessible language to test those concepts; yet, since it can be used pretty much as Haskell, often it leaves the programmer wandering through old concepts, without knowing where to apply dependent types. Some real world examples could help on that, so, what are good, concrete examples of programs that happen in practice, are simple to express as types, but complex to implement?

This is odd to me because my problem is that dependent types are needed everywhere. If you do not see that then look at programs this way.

Say we have f :: Ord a => [a] -> [a] (I will use the Haskell notations). What do we know about this function f? In other words, what can you predict about applications such as f [], f [5,8,7], f [1,1,2,2]? Say you know f x = [4,6,8] then what can you say about x? As you can observe, we know little.

Then suppose I told you the real name of f is sort. What can you tell me then about those same examples? What can you tell me about ys in relation to xs in f xs = ys? Now you know a lot, but where did this information come from? All I did was change the name of the function; this has no significance in the formal meaning of the program.

All this new information came from what you know about sorting. You know two defining characteristics:

  1. sort xs is a permutation of xs.
  2. sort xs is monotonically increasing.

We can use dependent typing to prove both of these properties for sort. Then, it isn't just a matter of our extrinsic understanding of sorting; the meaning of sorting becomes an intrinsic part of the program.

Catching bugs is a side effect. The real objective is to specify and formalise what we have to know in our heads anyways as part of the program.

Carefully reconsider the programs you have already written. What are the facts that make your program work that are only known in your head? These are all candidate examples.