[Haskell] 学习笔记4

[Haskell] 学习笔记4

Type declarations

The simplest way of declaring a new type is to introduce a new name for an existing type, using the type mechanism of Haskell

The following declaration from the standard prelude states that the type String is just a synonym for the type [Char] of lists of characters. The name of a new type must begin with a capital letter

Type declarations can be nested, in the sense that one such type can be declared in terms of another.

Type declarations cannot be recursive

Type declarations can also be parameterized by other types

Data declarations

A completely new type, as opposed to a synonym for an existing type, can be declared by specifying its values using the data mechanism of Haskell

For example, the following declaration from the standard prelude states that the type Bool comprises two new values, named False and True. In such declarations, the symbol | is read as or, and the new values of the type are called constructors. As with new types themselves, the names of new constructors must begin with a capital letter.

Note that the names given to new types and constructors have no inherent meaning to the Haskell system. For example, the above declaration could equally well be written as data A = B | C

Example:

The constructors in a data declaration can also have arguments:

Because of their use of arguments, the constructors Circle and Rect are actually constructor functions, which produce results of type Shape from arguments of type Float.

The difference between normal functions and constructor functions is that the latter have no defining equations, and exist purely for the purposes of building pieces of data, the expression Circle 1.0 is just a piece of data

Data declarations themselves can also be parameterized:

That is, a value of type Maybe a is either Nothing, or of the form Just x for some value x of type a. We can think of values of type Maybe a as being values of type a that may either fail or succeed, with Nothing representing failure, and Just representing success

Recursive types

The type of natural numbers from the previous section can also be declared in a recursive manner

That is, a value of type Nat is either Zero, or of the form Succ n for some value n of type Nat. Hence, this declaration gives rise to an infinite sequence of values, starting with the value Zero, and continuing by applying the constructor function Succ to the previous value in the sequence:

Zero…Succ Zero … Succ(Succ Zero)…Succ(Succ (Succ Zero))

Binary tree:

value occurs in a leaf if it matches the value at the leaf, and occurs in a node if it either matches the value at the node, occurs in the left subtree, or occurs in the right subtree.

Derived instances

When new types are declared, it is usually appropriate to make them into instances of a number of built-in classes. Haskell provides a simple facility for automatically making new types into instances of the classes Eq, Ord, Show, and Read, in the form of the deriving mechanism.

Note that for the purposes of deriving instances of the class Ord of ordered types, the ordering on the constructors of a type is determined by their position in its declaration