The Two Meanings of Declarative
For about the seventh time, now, I’ve been “corrected” on something in a way that isn’t really correct. The issue here is what is meant by a declarative language. Haskell and SQL are both called declarative. There are, though, very different senses in which these languages might qualify as declarative.
Haskell is a declarative language in that the program can be treated as a statement of facts, rather than as a set of commands that are sequenced in time. These facts, though, are about all sorts of things. They express the structure of the problem, but also the algorithms used to solve the problem, the intermediate data structures used between steps, and so on. I can implement merge sort, quick sort, and bubble sort in Haskell; and I can tell the difference.
SQL is a declarative language in that it’s a formal way for me to say what I want. The database decides how to find it. It’s true that there are some limitations: some databases perform far better with joins than with correlated IN clauses, for example. By and large, though, these are warts. I can’t describe most algorithms in SQL. It would be meaningless to try to identify whether an ORDER BY clause does a merge sort or bubble sort. The basic algorithms used by the system can depend on the definition of the table, the existence of indices, and even statistics gathered by the DBMS over time. You can bet your bottom dollar those algorithms aren’t themselves written in SQL (or even in PL/SQL or some other procedural extension).
These are, in other words, two different definitions of “declarative.” One language allows you to declare things about the computation. The other restricts you to declaring things about the problem. Critics and armchair observers would be well-advised to determine which is meant before blurting out “that doesn’t make sense, because Haskell is a declarative language.”