Uncanny Valleys in Declarative Language Design

Mark Miller, Daniel Von Dincklage, Vuk Ercegovac, Brian Chin
Editors: John Q. Open and Joan R. Acces; Article No   unpublished
When people write programs in conventional programming languages, they over-specify how to solve the problem they have in mind. Over-specification prevents the language's implementation from making many optimization decisions, leaving programmers with this burden. In more declarative languages, programmers over-specify less, enabling the implementation to make more choices for them. As these decisions improve, programmers shift more attention from implementation to their real problems. This
more » ... ess easily overshoots. When under-specified programs almost always work well enough, programmers rarely need to think about implementation details. As their understanding of implementation choices atrophies, the controls provided so they can override these decisions become obscure. Our declarative language project, Yedalog, is in the midst of this dilemma. The improvements in question make our users more productive, so we cannot simply retreat back towards over-specification. To proceed forward instead, we must meet some of the expectations we prematurely provoked, and our implementation's behavior must help users learn expectations more aligned with our intended semantics. These are general issues. Discussing their concrete manifestation in Yedalog should help other declarative systems that come to face these issues. 1 Background Kowalski famously observed[4] that "Algorithm = Logic + Control". Declarative languages enable users to ask logical questions. The "logic" of a declarative program is a description of what a correct answer looks like. The "control" explains how to compute answers that satisfy that description. Often these two components are not separate parts of a declarative program but distinct ways of reading a program. For example, the declarative reading of a Haskell program considers Haskell functions to be the mathematical functions they seem. The operational reading sees these functions as code explaining how to compute results from input arguments. In a declarative language, the computed results must be within the declarative reading's description. In declarative language design, there is an inescapable tradeoff between expressiveness and automation. General purpose declarative languages such as Haskell and Prolog are very expressive but with limited automation-incrementally more complex questions can be asked for incrementally more effort; but their users are responsible for controlling the direction of execution. Special purpose languages like Datalog and SQL are highly automated but with