Remix.run Logo
holowoodman 4 days ago

Problem is that those constraints are often very hard to express, even in more expressive languages.

One example would be integers. There are bigint-by-default languages like Haskell, where the type you usually use is an arbitrary-sized bigint. But usually you don't need that, and you usually know that something like a 32bit integer is sufficient. Often you get a int32 type that does that stuff for you. But then the question becomes about overflow behaviour, signedness, existence of -0, behaviour of -INT_MAX and stuff like that. Even in C, you are in undefined-behaviour-launch-the-rockets territory very quickly. And there are usually no "screw it, I don't care, give me whatever the CPU does" types. You don't get to choose your overflow/underflow behaviour. Often no bounded types either (unsigned integer day from 1 to 365). And if those types are available in libraries, the compiler won't be able to optimize.

There are tons more of those examples. It's always a compromise between the expressiveness that we want and that would be great, and the complexity that will make an implementation non-viable. So you get as much expressivenes as the language designer thinks he could maybe cram into his compiler. But it's always to much to be really optimized all the way through. And it's always too little for what one would actually need to be really exact.