I just recently stumbled over a paper from Karl Crary:
https://www.cs.cmu.edu/%7Ecrary/papers/2020/exsig.pdf
which aims to solve the “avoidance problem” aka “implicit abstraction” problem. Implicit abstractions occur, if a program does take advantage of a type that it doesn’t know about. The type can then be regarded as a hidden type parameter or an erased type. Type erasure allows for code reuse. With type erasure, programs can be combined freely – e.g. by using callback functions or a dynamic link library or by a “self” parameter. Dynamic solutions/applications aside, we can factorize every program into parts that have the type erasure property. If a program can be splitted into such parts, it then can take advantage of separate compilation. But the compiler should be able to sort it out, to derive it, to prove it. By doing this, the compiler has to derive existential signatures automatically. This is a very demanding task, especially when it is not clear by forehand where to set the splits. Quote:
From where should we take such a signature? Assuming that we have an appropriate signature calculus to solve this, we can go further, quote:
The quote continues with a rather ominous phrase:
because the compiler already has a synthetic view on the program (by using existentials), programmer’s interface gets added then, finally, the compiler will render a new synthesis. For the programmer roughly translated into:
“I wish… so please do something with my wishes and tell me if my dreams come true”.
The wishes – e.g. a library design enriched with independency (a constraint) will be respected as best as possible and the compiler will give a report about the result. If the constraints can’t be respected, it will still compile but the constraint(s) will be removed : “Please redesign your library” and the compiler might even tell what needs to be changed.
The quote ends with:
Crary makes clear here that he doesn’t want to change the underlying language (ML). The compiler has to be at its own, a primary goal, no burden for the programmer. But for imperative languages, the “burden” (written as constraints) might be regarded as an extra improvement.
These are steep claims aren’t they? And what do modern programming languages typically offer for that?
I deeply apologize for the inconvenience. A bit of an irony here: I took the quotes entirely from section 6.3 , headline "practicum". They are the least technical part of the entire paper. I added some context about the motivation , side effects and relevance for imperative languages. If you want to read some code related to the issue, I'd like to mention the thread:
https://forum.nim-lang.org/t/8728
You can find some C++ code there. I had preferred to give some Nim code instead. But I couldn't. So I asked for a solution in Nim. If you want to contribute - it would be highly appreciated!