I think having simple and direct denotational semantics necessarily means having relatively complex, indirect operational semantics (e.g: Haskell). Having a simple and direct operational semantics necessarily means having complex and indirect denotational semantics (e.g: C).
C makes performance easy and correctness hard.
Haskell makes correctness easy and performance hard.
The trick is, in most programs, you only need performance for a tiny subset of the program. You need correctness throughout the whole program.
Comments
I think having simple and direct denotational semantics necessarily means having relatively complex, indirect operational semantics (e.g: Haskell). Having a simple and direct operational semantics necessarily means having complex and indirect denotational semantics (e.g: C).
C makes performance easy and correctness hard. Haskell makes correctness easy and performance hard.
The trick is, in most programs, you only need performance for a tiny subset of the program. You need correctness throughout the whole program.
Why do you think that there must be a tradeoff between simplicity of denotational and operational semantics?
Because operational semantics (of contemporary computers, at least) are very different from a simple denotational semantics.
We have to bridge that gap:
1) Either use a compiler that hides away the operational details
2) Or use a language that directly maps to the operational semantics, but then is necessarily far away from the denotational ones