
	Haskell: The Craft of Functional Programming
	Simon Thompson
	(c) Addison-Wesley, 1999.

	Chapter 14, part 1

>	module Chapter14_1 where

>	import Prelude hiding (Either(..),either,Maybe(..),maybe)

Algebraic types
^^^^^^^^^^^^^^^

Introducing algebraic types
^^^^^^^^^^^^^^^^^^^^^^^^^^^

We give a sequence of examples of increasing complexity ...

Enumerated types
^^^^^^^^^^^^^^^^
Two enumerated types

>	data Temp   = Cold | Hot
>	data Season = Spring | Summer | Autumn | Winter

A function over Season, defined using pattern matching.

>	weather :: Season -> Temp

>	weather Summer = Hot
>	weather _      = Cold

The Ordering type, as used in the class Ord.

	data Ordering = LT | EQ | GT

Declaring Temp an instance of Eq.

>	instance Eq Temp where
>	  Cold == Cold  = True
>	  Hot  == Hot   = True
>	  _    == _     = False

Product types
^^^^^^^^^^^^^

A person is represented by their name and age ...

>	data People = Person Name Age

where Name and Age are the appropriate synonyms.

>	type Name = String
>	type Age  = Int

>	jemima, ronnie :: People
>	jemima = Person "Electric Aunt Jemima" 77
>	ronnie = Person "Ronnie" 14

Turning a person into a string.

>	showPerson :: People -> String
>	showPerson (Person st n) = st ++ " -- " ++ show n

An alternative to Age,

>	data NewAge = Years Int


Alternatives
^^^^^^^^^^^^

A shape in a simple geometrical program is either a circle or a
rectangle. These alternatives are given by the type

>	data Shape = Circle Float |
>	             Rectangle Float Float

>	shape1 = Circle 3.0
>	shape2 = Rectangle 45.9 87.6

Pattern matching allows us to define functions by cases, as in,

>	isRound :: Shape -> Bool
>	isRound (Circle _)      = True
>	isRound (Rectangle _ _) = False

and also lets us use the components of the elements:

>	area :: Shape -> Float
>	area (Circle r)      = pi*r*r
>	area (Rectangle h w) = h*w

Derived instances ...

	data Season = Spring | Summer | Autumn | Winter 
	              deriving (Eq,Ord,Enum,Show,Read)


	data Shape  = Circle Float | 
	              Rectangle Float Float 
	              deriving (Eq,Ord,Show,Read)

Recursive algebraic types
^^^^^^^^^^^^^^^^^^^^^^^^^

Expressions
^^^^^^^^^^^

Representing an integer expression.

>	data Expr = Lit Int |
>	            Add Expr Expr |
>	            Sub Expr Expr

Three examples from Expr.

>	expr1 = Lit 2
>	expr2 = Add (Lit 2) (Lit 3)
>	expr3 = Add (Sub (Lit 3) (Lit 1)) (Lit 3)  

Evaluating an expression.

>	eval :: Expr -> Int

>	eval (Lit n)     = n
>	eval (Add e1 e2) = (eval e1) + (eval e2)
>	eval (Sub e1 e2) = (eval e1) - (eval e2)

Showing an expression.

	instance Show Expr where

	  show (Lit n) = show n
	  show (Add e1 e2) 
	    = "(" ++ show e1 ++ "+" ++ show e2 ++ ")"
	  show (Sub e1 e2) 
	    = "(" ++ show e1 ++ "-" ++ show e2 ++ ")"


Trees of integers
^^^^^^^^^^^^^^^^^

The type definition.

>	data NTree = NilT |
>	             NodeT Int NTree NTree

Example trees

>	treeEx1 = NodeT 10 NilT NilT
>	treeEx2 = NodeT 17 (NodeT 14 NilT NilT) (NodeT 20 NilT NilT)

Definitions of many functions are primitive recursive. For instance,

>	sumTree,depth :: NTree -> Int

>	sumTree NilT           = 0
>	sumTree (NodeT n t1 t2) = n + sumTree t1 + sumTree t2

>	depth NilT             = 0
>	depth (NodeT n t1 t2)   = 1 + max (depth t1) (depth t2)

How many times does an integer occur in a tree?

>	occurs :: NTree -> Int -> Int

>	occurs NilT p = 0
>	occurs (NodeT n t1 t2) p
>	  | n==p        = 1 + occurs t1 p + occurs t2 p
>	  | otherwise   =     occurs t1 p + occurs t2 p


Rearranging expressions
^^^^^^^^^^^^^^^^^^^^^^^

Right-associating additions in expressions.

>	assoc :: Expr -> Expr

>	assoc (Add (Add e1 e2) e3)
>	  = assoc (Add e1 (Add e2 e3)) 
>	assoc (Add e1 e2) 
>	  = Add (assoc e1) (assoc e2) 
>	assoc (Sub e1 e2) 
>	  = Sub (assoc e1) (assoc e2)
>	assoc (Lit n) 
>	  = Lit n
 

Infix constructors
^^^^^^^^^^^^^^^^^^

An alternative definition of Expr.

>	data Expr' = Lit' Int |
>	             Expr' :+: Expr' |
>	             Expr' :-: Expr'



Mutual Recursion
^^^^^^^^^^^^^^^^

Mutually recursive types ...

	data Person = Adult Name Address Biog |
	              Child Name
	data Biog   = Parent String [Person] |
	              NonParent String

... and functions.

	showPerson (Adult nm ad bio) 
	  = show nm ++ show ad ++ showBiog bio
	showBiog (Parent st perList)
	  = st ++ concat (map showPerson perList)

Alternative definition of Expr (as used later in the calculator case
study.

data Expr = Lit Int |
            Op Ops Expr Expr

data Ops  = Add | Sub | Mul | Div 

It is possible to extend the type Expr so that it contains
conditional expressions, \texttt{If b e1 e2}.

data Expr = Lit Int |
            Op Ops Expr Expr |
            If BExp Expr Expr

Boolean expressions.

>	data BExp = BoolLit Bool |
>	            And BExp BExp |
>	            Not BExp |
>	            Equal Expr Expr |
>	            Greater Expr Expr






