Haskell——《Real-World-Haskell》Chapter1

State the facts and suspend judgment

A brief sketch of Haskell's history

From Real World Haskell

The development of Haskell is rooted in mathematics and computer science research.

Prehistory

A few decades before modern computers were invented, the mathematician Alonzo Church developed a language called the lambda calculus. He intended it as a tool for investigating the foundations of mathematics. The first person to realize the practical connection between programming and the lambda calculus was John McCarthy, who created Lisp in 1958.

During the 1960s, computer scientists began to recognise and study the importance of the lambda calculus. Peter Landin and Christopher Strachey developed ideas about the foundations of programming languages: how to reason about what they do (operational semantics) and how to understand what they mean (denotational semantics).

So what is the concrete definition of operational semantics and denotational semantics?

In the early 1970s, Robin Milner created a more rigorous functional programming language named ML. While ML was developed to help with automated proofs of mathematical theorems, it gained a following for more general computing tasks.

The 1970s saw the emergence of lazy evaluation as a novel strategy. David Turner developed SASL and KRC, while Rod Burstall and John Darlington developed NPL and Hope. NPL, KRC and ML influenced the development of several more languages in the 1980s, including Lazy ML, Clean, and Miranda.

Early antiquity

By the late 1980s, the efforts of researchers working on lazy functional languages were scattered across more than a dozen languages. Concerned by this diffusion of effort, a number of researchers decided to form a committee to design a common language. After three years of work, the committee published the Haskell 1.0 specification in 1990. It named the language after Haskell Curry, an influential logician.

Many people are rightfully suspicious of “design by committee”, but the work of the Haskell committee is a beautiful example of the best work a committee can do. They produced an elegant, considered language design, and succeeded in unifying the fractured efforts of their research community. Of the thicket of lazy functional languages that existed in 1990, only Haskell is still actively used.

Since its publication in 1990, the Haskell language standard has seen five revisions, most recently in 1998. A number of Haskell implementations have been written, and several are still actively developed.

During the 1990s, Haskell served two main purposes. On one side, it gave language researchers a stable language in which to experiment with making lazy functional programs run efficiently. Other researchers explored how to construct programs using lazy functional techniques. Still others used it as a teaching language.

The modern era

While these basic explorations of the 1990s proceeded, Haskell remained firmly an academic affair. The informal slogan of those inside the community was to “avoid success at all costs”. Few outsiders had heard of the language at all. Indeed, functional programming as a field was quite obscure.

During this time, the mainstream programming world experimented with relatively small tweaks: from programming in C, to C++, to Java. Meanwhile, on the fringes, programmers were beginning to tinker with new, more dynamic languages. Guido van Rossum designed Python; Larry Wall created Perl; and Yukihiro Matsumoto developed Ruby.

As these newer languages began to seep into wider use, they spread some crucial ideas. The first was that programmers are not merely capable of working in expressive languages; in fact, they flourish. The second was in part a byproduct of the rapid growth in raw computing power of that era: it's often smart to sacrifice some execution performance in exchange for a big increase in programmer productivity. Finally, several of these languages borrowed from functional programming.

Over the past half a decade, Haskell has successfully escaped from academia, buoyed in part by the visibility of Python, Ruby, and even Javascript. The language now has a vibrant and fast-growing culture of open source and commercial users, and researchers continue to use it to push the boundaries of performance and expressiveness.

Chapter 1. Getting Started

Haskell environment

Use Glasgow Haskell Compiler (GHC) which has three main components.

  • ghc: an optimizing compiler that generates fast native code.
  • ghci: an interactive interpreter and debugger. (similar to python in Python and the utop in OCaml)
  • runghc: a program for running Haskell programs as scripts, without needing to compile them first.

Small tips about the ghci prompt

The prompt displayed by ghci changes frequently depending on what modules we have loaded (Prelude module is sometimes referred to as "the standard prelude"). It can often grow too long with little visual room left.

For brevity and consistency, we have replaced ghci's default prompts.

1
2
Prelude> :set prompt "ghci> "
ghci>

Basic interaction: using ghci as a calculator

Just skip most of this session...

Pay attention to Boolean logic, operators and value comparisions.

While some programming languages treat the number zero as synonymous with False, Haskell does not, nor does it consider a non-zero value to be True.

1
True && 1
1
2
3
4
5
<interactive>:1:9: error:
• No instance for (Num Bool) arising from the literal ‘1’
• In the second argument of ‘(&&)’, namely ‘1’
In the expression: True && 1
In an equation for ‘it’: it = True && 1

Lists

Notation is similar to Lists in OCaml. The empty list is written [], but Haskell use commas to separate elements in the list (instead of semicomma in OCaml).

1
2
3
[1,2,3]
[]
["foo", "test", "right"]

Al elements of a list must be of the same type.

enumeration notation: using this, Haskell will fill in the contents of the list for us.

When we write an enumeration, we can optionally specify the size of the step to use by providing the first two elements, followed by the value at which to stop generating the enumeration.

1
2
3
4
5
6
7
8
ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]
ghci> [1.0,1.25..2.0]
[1.0,1.25,1.5,1.75,2.0]
ghci> [1,4..15]
[1,4,7,10,13]
ghci> [10,9..1]
[10,9,8,7,6,5,4,3,2,1]

We use operator ++ to concatenate two lists (the same to OCaml) and : operator to add an element to the front of a list (similar to :: in OCaml).

First steps with types

Haskell requires type names tostart with an uppercase letter, and variable names must start with a lowercase letter. Bear this in mind!

With the help of :set +t and :type command in ghci. Ghci will print type information for any expression we give it.

Like this

1
2
3
4
5
6
7
8
9
10
11
ghci> :set +t
ghci> 'c'
'c'
it :: Char
ghci> "foo"
"foo"
it :: [Char]

ghci> 7 ^ 80
40536215597144386832065866109016673800875222251012083746192454448001
it :: Integer

Haskell, see more of this style of type annotation in Chapter 6, Using Typeclasses. Jump to Chap6!