0% found this document useful (0 votes)
86 views22 pages

Programming in Haskell: Chapter 8 - Declaring Types and Classes

The document discusses type declarations and data declarations in Haskell. Type declarations allow defining synonyms for existing types, like defining String as a synonym for [Char]. Data declarations allow defining new types with associated constructors, like defining a Bool type with False and True constructors. Recursive types can also be declared, like defining a Nat type recursively in terms of Zero and Succ. Functions on new types can be defined recursively, like adding two Nat values. The document provides examples of declaring types for arithmetic expressions and binary trees.

Uploaded by

Tân Đinh Như
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
86 views22 pages

Programming in Haskell: Chapter 8 - Declaring Types and Classes

The document discusses type declarations and data declarations in Haskell. Type declarations allow defining synonyms for existing types, like defining String as a synonym for [Char]. Data declarations allow defining new types with associated constructors, like defining a Bool type with False and True constructors. Recursive types can also be declared, like defining a Nat type recursively in terms of Zero and Succ. Functions on new types can be defined recursively, like adding two Nat values. The document provides examples of declaring types for arithmetic expressions and binary trees.

Uploaded by

Tân Đinh Như
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 22

PROGRAMMING IN HASKELL

Chapter 8 - Declaring Types and Classes

1
Type Declarations

In Haskell, a new name for an existing type can be


defined using a type declaration.

type String = [Char]

String is a synonym for the type [Char].

2
Type declarations can be used to make other types
easier to read. For example, given

type Pos = (Int,Int)

we can define:

origin :: Pos
origin = (0,0)

left :: Pos  Pos


left (x,y) = (x-1,y)
3
Like function definitions, type declarations can also
have parameters. For example, given

type Pair a = (a,a)

we can define:

mult :: Pair Int  Int


mult (m,n) = m*n

copy :: a  Pair a
copy x = (x,x)
4
Type declarations can be nested:

type Pos = (Int,Int)

type Trans = Pos  Pos

However, they cannot be recursive:

type Tree = (Int,[Tree])

5
Data Declarations

A completely new type can be defined by specifying


its values using a data declaration.

data Bool = False | True

Bool is a new type, with two


new values False and True.
6
Note:

 The two values False and True are called the


constructors for the type Bool.

 Type and constructor names must always begin


with an upper-case letter.

 Data declarations are similar to context free


grammars. The former specifies the values of
a type, the latter the sentences of a language.

7
Values of new types can be used in the same ways
as those of built in types. For example, given

data Answer = Yes | No | Unknown

we can define:

answers :: [Answer]
answers = [Yes,No,Unknown]

flip :: Answer  Answer


flip Yes = No
flip No = Yes
flip Unknown = Unknown
8
The constructors in a data declaration can also have
parameters. For example, given

data Shape = Circle Float


| Rect Float Float

we can define:

square :: Float  Shape


square n = Rect n n

area :: Shape  Float


area (Circle r) = pi * r^2
area (Rect x y) = x * y
9
Note:

 Shape has values of the form Circle r where r is


a float, and Rect x y where x and y are floats.

 Circle and Rect can be viewed as functions that


construct values of type Shape:

Circle :: Float  Shape

Rect :: Float  Float  Shape

10
Not surprisingly, data declarations themselves can
also have parameters. For example, given

data Maybe a = Nothing | Just a

we can define:

safediv :: Int  Int  Maybe Int


safediv _ 0 = Nothing
safediv m n = Just (m `div` n)

safehead :: [a]  Maybe a


safehead [] = Nothing
safehead xs = Just (head xs)
11
Recursive Types

In Haskell, new types can be declared in terms of


themselves. That is, types can be recursive.

data Nat = Zero | Succ Nat

Nat is a new type, with constructors


Zero :: Nat and Succ :: Nat  Nat.
12
Note:

 A value of type Nat is either Zero, or of the form


Succ n where n :: Nat. That is, Nat contains the
following infinite sequence of values:

Zero

Succ Zero

Succ (Succ Zero)





13
 We can think of values of type Nat as natural
numbers, where Zero represents 0, and Succ
represents the successor function 1+.

 For example, the value

Succ (Succ (Succ Zero))

represents the natural number

1 + (1 + (1 + 0)) = 3
14
Using recursion, it is easy to define functions that
convert between values of type Nat and Int:

nat2int :: Nat  Int


nat2int Zero =0
nat2int (Succ n) = 1 + nat2int n

int2nat :: Int  Nat


int2nat 0 = Zero
int2nat n = Succ (int2nat (n-1))

15
Two naturals can be added by converting them to
integers, adding, and then converting back:

add :: Nat  Nat  Nat


add m n = int2nat (nat2int m + nat2int n)

However, using recursion the function add can be


defined without the need for conversions:

add Zero n=n


add (Succ m) n = Succ (add m n)
16
For example:

add (Succ (Succ Zero)) (Succ Zero)


=
Succ (add (Succ Zero) (Succ Zero))
=
Succ (Succ (add Zero (Succ Zero))
=
Succ (Succ (Succ Zero))

Note:

 The recursive definition for add corresponds to


the laws 0+n = n and (1+m)+n = 1+(m+n).
17
Arithmetic Expressions

Consider a simple form of expressions built up from


integers using addition and multiplication.

1 

2 3

18
Using recursion, a suitable new type to represent
such expressions can be declared by:

data Expr = Val Int


| Add Expr Expr
| Mul Expr Expr

For example, the expression on the previous slide


would be represented as follows:

Add (Val 1) (Mul (Val 2) (Val 3))

19
Using recursion, it is now easy to define functions
that process expressions. For example:

size :: Expr  Int


size (Val n) = 1
size (Add x y) = size x + size y
size (Mul x y) = size x + size y

eval :: Expr  Int


eval (Val n) = n
eval (Add x y) = eval x + eval y
eval (Mul x y) = eval x * eval y
20
Note:

 The three constructors have types:

Val :: Int  Expr


Add :: Expr  Expr  Expr
Mul :: Expr  Expr  Expr

 Many functions on expressions can be defined


by replacing the constructors by other functions
using a suitable fold function. For example:

eval = folde id (+) (*)


21
Exercises

(1) Using recursion and the function add, define a


function that multiplies two natural numbers.

(2) Define a suitable function folde for expressions


and give a few examples of its use.

(3) Define a type Tree a of binary trees built from


Leaf values of type a using a Node constructor
that takes two binary trees as parameters.
22

You might also like