Haskell as a Lens
Ruby was the language that sparked our examination of names, types, functions, and objects. We now turn our attention to Haskell, a language that is very different from the imperative languages that have likely dominated your learning. We will revisit the topics introduced earlier but also encounter a few new ones that are especially relevant to Haskell and other functional languages.
Functional languages are functional because they promote functions as the most important building block for writing programs. They also some lack some features that we consider vital in imperative languages, like loops and mutability. A surplus of these languages emerged in the 1980s. A supergroup of programming language researchers and academics decided to coordinate their efforts and build a superlanguage that would unify the fractured functional programming community. The result was Haskell, the first specification of which was released in 1990. The language was named after Haskell Curry, a mathematician whose theoretical work showed that computer programs could double as mathematical proofs and who popularized a scheme for building multiple-parameter functions out of simpler single-parameter functions. After the language was revealed, Curry's widow informed the language committee that her husband despised his first name. Too late. The name was immutable.
The Haskell language has grown over the last 30 years but has never reached a level of adoption that would make it a household name. You may question the utility of studying a language that you haven't heard of before, but a language's popularity is not a reliable measure of its worth. Companies big and small do employ Haskell programmers and fund its open-source development. Meta uses Haskell to fight spam on Facebook. Tesla uses it to run self-driving cars. Co-star proudly uses Haskell to power their astrology app. The New York Times uses it to power parts of their website.
There are several reasons to study Haskell even though it has not wooed developers to the same degree as JavaScript, C++, and Java. First, Haskell presents the ideas of functional programming in an ultra-concentrated form, and you can't help but learn these ideas as you work with the language. You can then take these ideas to other languages. Second, new programming language ideas are more likely to appear in smaller research languages like Haskell. Mainstream languages will always lag in features because they are encumbered by technological inertia. Third, software written in Haskell tends to be safe and fast. Companies use many languages across their product line, playing to the strengths of each language. Haskell has a reputation for being used to rewrite components that run slowly or have concurrency bugs. Programs rewritten in Haskell are generally faster to develop, have fewer bugs, and require less code.
In this chapter, we introduce Haskell and briefly examine one of several ways to define functions. But we focus on the basic building block of functions: expressions, which are snippets of code that yield a value. Expressions are in contrast to statements, which don't produce values but instead alter memory and perform input or output. By the end of the chapter, you'll be able to answer the following questions:
- What is Haskell's type system? Are types explicit, implicit, or inferred? Is typechecking performed statically or dynamically? How are functions written polymorphically so they can serve many types?
- Simple expressions are glued together by operators to form compound expressions. What qualities are ascribed to these operators? Can new ones be defined?
- How does a programmer choose between values using conditional logic?
- When and how is an expression evaluated?
Haskell is the language we have chosen as a lens to examine expressions and functional programming. We could instead have chosen a language from the Lisp family, whose best-known dialects are Common Lisp, Racket, Scheme, and Clojure. The designers of these languages have contributed a number of significant ideas to programming language design, including garbage collection, recursive functions and data structures, and dynamic typing. That we did not choose one of these languages is largely a matter of chance and personal taste, not of some objective rank.