A total (functional) language is one in which everything can be shown to terminate. Obviously, there are lots of places where I don't want this - throwing exceptions is sometimes handy, a web-server isn't supposed to terminate, etc. But sometimes, I would like a local totality check to enable certain optimizations. For example, if I have a provably-total function
commutativity :: forall (n :: Nat) (m :: Nat). n + m :~: m + n
commutativity = ...
then, since :~:
has exactly one inhabitant (Refl
), GHC could optimize
gcastWith (commutativity @n @m) someExpression
==>
someExpression
And my proof of commutativity goes from having an O(n)
runtime cost to being free. So, now for my question:
What are some of the subtle difficulties in making a totality checker for Haskell?
Obviously, such a checker is conservative so whenever GHC isn't sure something is total (or is to lazy to check) it could assume it isn't... Seems to me it might not be too difficult to cobble together a not-so-smart checker that would still be very useful (at least it should be straightforward to eliminate all my arithmetic proofs). Yet, I can't seem to find any efforts to build such a thing into GHC, so obviously I'm missing some pretty big constraints. Go ahead SO, crush my dreams. :)
Relevant but not recent: Unfailing Haskell by Neil Mitchell, 2005.
a :~: b
only has one non-⊥ inhabitant, if we were in a total setting, we could say that proofs ofa :~: b
had no computational content; we know thatcastWith :: (a :~: b) -> a -> b
must be computationally equivalent toconst id
(given totality). In a homotopy type theory setting, it's true that equalities have computational content, so you'd have to do the work – but in that setting,refl
isn't the only inhabitant ofa = b
! – Antal Spector-Zabuskya:~:b
. Everytime one hase :: a:~:b
and a termination checker ensurese
is non bottom, once can optimize it withunsafeCoerce Refl
. The tricky part is proving totality on Haskell codata, where induction is not enough. Maybe we could restrict this to "data"-only types/kinds, like e.g.data Nat = O | S !Nat
, where induction could be sound. I am not terribly confident about this, though. – chi:~:
is a boxed type, it has 2 inhabitants:Refl
and_|_
. – Heimdell