Musings about Language Design
In this lesson we’ve got no code for you; instead, here are some musings about language design informed by our discussion so far.
We'll cover the following...
Balance Between Generality and Specificity of a Feature
One of the most important questions to ask when designing a language feature is: what should the balance be between generality and specificity of a feature?
Our go-to example is LINQ, and what we’ve been talking about for the last lessons illustrates the problem nicely.
As we’ve seen many times in this course, query comprehensions allow us to express projection (Select
) concisely, binding (SelectMany
) and use of the zero of an additive monad (Where
) to express a condition. Because C# uses a syntactic transformation to implement LINQ, we can show these concepts on an instance of any monad that has the right methods. The compiler does not know or care whether the thing being selected is a sequence, a probability distribution, whatever, doesn’t matter. All that matters is that a method with the right signature is available as an instance or extension method.
The language designers for C# 3.0 were therefore faced with a choice: how general should the LINQ feature be? There’s a spectrum of possibilities; a few points on that spectrum are:
-
Monad is just a monoid in the category of endofunctors, which implies that there are other patterns like “monoid” and “category” and “functor” that we could describe in the type system; what’s so special about monads? We could create a whole “higher-kinded” type system to describe generic type patterns; “monad” is just one possible pattern.
-
We could embbed monads as a special kind of thing right into the language, using the ...