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

	Chapter 14, part 2

>	module Chapter14_2 where

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

Algebraic types, part 2
^^^^^^^^^^^^^^^^^^^^^^^


Polymorphic algebraic types
^^^^^^^^^^^^^^^^^^^^^^^^^^^

A type of pairs of elements, taken from the same type.

>	data Pairs a = Pr a a

and example elements of the type are

>	pair1 = Pr 2 3    :: Pairs Int
>	pair2 = Pr [] [3] :: Pairs [Int]
>	pair3 = Pr [] []  :: Pairs [a]

Are the two halves equal?

>	equalPair :: Eq a => Pairs a -> Bool
>	equalPair (Pr x y) = (x==y)


Lists
^^^^^

Defining lists from scratch (which loses some of the special syntax for
lists).

>	data List a = NilList | Cons a (List a)
>	              deriving (Eq,Ord,Show,Read)

Binary trees
^^^^^^^^^^^^


Binary trees carrying elements of an arbitrary type.

>	data Tree a = Nil | Node a (Tree a) (Tree a)
>	              deriving (Eq,Ord,Show,Read)

The depth of a binary tree.

>	depthT :: Tree a -> Int
>	depthT Nil            = 0
>	depthT (Node n t1 t2) = 1 + max (depthT t1) (depthT t2)

Turning a tree into a list.

>	collapse :: Tree a -> [a]
>	collapse Nil = []
>	collapse (Node x t1 t2)
>	  = collapse t1 ++ [x] ++ collapse t2
 
For example,
 
>	collapseEG 
>	 = collapse (Node 12 
>	               (Node 34 Nil Nil) 
>	               (Node 3 (Node 17 Nil Nil) Nil))

Mapping a function over all elements in a tree, preserving the
structure.

>	mapTree :: (a -> b) -> Tree a -> Tree b
>	mapTree f Nil = Nil
>	mapTree f (Node x t1 t2)
>	  = Node (f x) (mapTree f t1) (mapTree f t2)


The union type, Either
^^^^^^^^^^^^^^^^^^^^^^

A union type -- defined in the Prelude.lhs.

>	data Either a b = Left a | Right b
>	                  deriving (Eq,Ord,Read,Show)

Examples

>	eitherEG1 = Left "Duke of Prunes" :: Either String Int
>	eitherEG2 = Right 33312           :: Either String Int

In the left or the right?

>	isLeft :: Either a b -> Bool
>	isLeft (Left _)  = True
>	isLeft (Right _) = False

To define a function from Either a b to c we have to deal with two cases,

>	either :: (a -> c) -> (b -> c) -> Either a b -> c

>	either f g (Left x)  = f x
>	either f g (Right y) = g y


If we have a function f::a -> cand we wish to apply it to an element
of Either a b, there is a problem: what do we do if the element is
in the right-hand side of the Either type? A simple answer is to raise an error

>	applyLeft :: (a -> c) -> Either a b -> c

>	applyLeft f (Left x)  = f x
>	applyLeft f (Right _) = error "applyLeft applied to Right"

Arbitrarily branching trees

>	data GTree a = Leaf a | Gnode [GTree a]


Case study: Program Errors
^^^^^^^^^^^^^^^^^^^^^^^^^^

This section explores various ways of handling errors raised in program
execution.

\subsection*{Dummy Values}
\index{dummy values at errors}

The tail function re-defined to give an empty list when applied to the empty list. 

>	tl :: [a] -> [a]
>	tl (_:xs) = xs
>	tl []     = []

Zero returned when division by zero,

>	divide :: Int -> Int -> Int
>	divide n m 
>	  | (m /= 0)    = n `div` m
>	  | otherwise   = 0

Head redefined to give a dummy value on the empty list; the value has
to be a parameter.

>	hd :: a -> [a] -> a
>	hd y (x:_) = x
>	hd y []    = y

Error types
^^^^^^^^^^^

The Maybe type, as defined in the Prelude.lhs,

>	data Maybe a = Nothing | Just a
>	               deriving (Eq,Ord,Read,Show)

An error-raising division function

>	errDiv :: Int -> Int -> Maybe Int
>	errDiv n m 
>	  | (m /= 0)    = Just (n `div` m)
>	  | otherwise   = Nothing 

The function mapMaybe transmits an error value though the application of
the function g. 

>	mapMaybe :: (a -> b) -> Maybe a -> Maybe b

>	mapMaybe g Nothing  = Nothing
>	mapMaybe g (Just x) = Just (g x)

In trapping an error, we aim to return a result of type b, from an
input of type Maybe a; there are two cases to deal with:
normal result (Just); error (Nothing).

>	maybe :: b -> (a -> b) -> Maybe a -> b

>	maybe n f Nothing  = n
>	maybe n f (Just x) = f x

Examples

>	handle1, handle2 :: Int
>	handle1 = maybe 56 (1+) (mapMaybe (*3) (errDiv 9 0)) 
>	handle2 = maybe 56 (1+) (mapMaybe (*3) (errDiv 9 1))  

Generalising the Maybe type to include an error message in the `Nothing'
part.

>	data Err a = OK a | Error String


Design with Algebraic Data Types
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Case study: edit distance
^^^^^^^^^^^^^^^^^^^^^^^^^

A type to represent the different sorts of Edit operations.

>	data Edit = Change Char |
>	            Copy |
>	            Delete |
>	            Insert Char |
>	            Kill  
>	            deriving (Eq,Show)

Transforming one string into another, optimally,

>	transform :: String -> String -> [Edit]

>	transform [] [] = []
>	transform xs [] = [Kill]
>	transform [] ys = map Insert ys
>	transform (x:xs) (y:ys)
>	  | x==y        = Copy : transform xs ys
>	  | otherwise   = best [ Delete   : transform xs (y:ys) ,
>	                         Insert y : transform (x:xs) ys ,
>	                         Change y : transform xs ys ]
 
How do we choose the best sequence? We choose the one with the lowest
cost.

>	best :: [[Edit]] -> [Edit]

>	best [x]   = x
>	best (x:xs) 
>	  | cost x <= cost b    = x
>	  | otherwise           = b
>	      where 
>	      b = best xs

The cost is given by charging one for every operation except copy,
which is equivalent to `leave unchanged'.

>	cost :: [Edit] -> Int

>	cost = length . filter (/=Copy)

Simulation
^^^^^^^^^^

NOTE: details of the Simulation case study are collected separately.

 
Algebraic types and type classes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Movable objects
^^^^^^^^^^^^^^^

>	data Vector = Vec Float Float

>	class Movable a where
>	  move      :: Vector -> a -> a
>	  reflectX  :: a -> a
>	  reflectY  :: a -> a
>	  rotate180 :: a -> a
>	  rotate180 = reflectX . reflectY

>	data Point = Point Float Float 
>	             deriving Show

>	instance Movable Point where
>	  move (Vec v1 v2) (Point c1 c2) = Point (c1+v1) (c2+v2)
>	  reflectX (Point c1 c2)  = Point c1 (-c2)
>	  reflectY (Point c1 c2)  = Point (-c1) c2
>	  rotate180 (Point c1 c2) = Point (-c1) (-c2)

>	data Figure = Line Point Point |
>	              Circle Point Float 
>	              deriving Show

>	instance Movable Figure where
>	  move v (Line p1 p2) = Line (move v p1) (move v p2)
>	  move v (Circle p r) = Circle (move v p) r

>	  reflectX (Line p1 p2) = Line (reflectX p1) (reflectX p2)
>	  reflectX (Circle p r) = Circle (reflectX p) r

>	  reflectY (Line p1 p2) = Line (reflectY p1) (reflectY p2)
>	  reflectY (Circle p r) = Circle (reflectY p) r

>	instance Movable a => Movable [a] where
>	  move v   = map (move v)
>	  reflectX = map reflectX
>	  reflectY = map reflectY


Named objects
^^^^^^^^^^^^^

Named objects:

>	class Named a where
>	  lookName :: a -> String
>	  giveName :: String -> a -> a

A named type ...

>	data Name a = Pair a String

... as witnessed by the instance declaration.

>	instance Named (Name a) where
>	  lookName (Pair obj nm) = nm
>	  giveName nm (Pair obj _) = (Pair obj nm)

Putting together classes
^^^^^^^^^^^^^^^^^^^^^^^^

See the text for details of what is going on here.

>	mapName :: (a -> b) -> Name a -> Name b

>	mapName f (Pair obj nm) = Pair (f obj) nm

>	instance Movable a => Movable (Name a) where
>	  move v   = mapName (move v)
>	  reflectX = mapName reflectX
>	  reflectY = mapName reflectY

>	class (Movable b, Named b) => NamedMovable b

>	instance Movable a => NamedMovable (Name a)




Reasoning about algebraic types
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The functions discussed here are all defined elsewhere.



