© m. winter cosc 4p41 – functional programming 6.16.1 enumerated types data temp = cold | hot...

32
© M. Winter COSC 4P41 – Functional Programming 6.1 Enumerated types data Temp = Cold | Hot data Season = Spring | Summer | Autumn | Winter weather :: Season -> Temp weather Summer = Hot weather _ = Cold Examples from Prelude.hs: data Bool = False | True data Ordering = LT | EQ | GT

Upload: clarence-shields

Post on 27-Dec-2015

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.1

Enumerated types

data Temp = Cold | Hot

data Season = Spring | Summer | Autumn | Winter

weather :: Season -> Temp

weather Summer = Hot

weather _ = Cold

Examples from Prelude.hs:

data Bool = False | True

data Ordering = LT | EQ | GT

Page 2: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.2

Product types

type Name= String

type Age = Int

data People = Person Name Age

Examples values of type People:

Person ”Electric Aunt Jemima” 77

Person ”Ronnie” 14

Person :: Name -> Age -> People

Page 3: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.3

Algebraic types vs Type synonyms

Type synonyms: type People = (Name,Age)

Advantages of algebraic types

• Each object of the type carries an explicit label of the purpose of the element.

• It is not possible accidentally to treat an arbitrary pair consisting of a string and a number as a person.

• The type will appear in any error messages due to mis-typing.• The principle of information hiding can be applied (in connection

with modules).

Advantages of type synonyms:

• The elements are more compact, and so definitions will be shorter.• Using a pair allows us to reuse many polymorphic functions such as

fst and snd.

Page 4: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.4

Alternatives

data Shape = Circle Float

| Rectangle Float Float

isRound :: Shape -> Bool

isRound (Circle _) = True

isRound (Rectangle _ _) = False

area :: Shape -> Float

area (Circle r) = pi*r*r

area (Rectangle h w) = h*w

Circle :: Float -> Shape

Rectangle :: Float -> Float -> Shape

Page 5: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.5

Algebraic types

General form of algebraic type definitions

data Typename

= Con1 t11 … t1k1

| Con2 t21 … t2k2

| Conn tn1 … tnkn

This defines constructor functions with the following types

Coni :: ti1 -> … -> tiki -> Typename

Page 6: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.6

Derived instances

For a new algebraic type Haskell can derive default implementations for

several overloaded functions. Examples:

data Season = Spring | Summer | Autumn | Winter

deriving (Eq,Ord,Enum,Show,Read)

data Shape = Circle Float

| Rectangle Float Float

deriving (Eq,Ord,Show,Read)

• We cannot expect that elements of Shape can be enumerated (being in Enum can only be derived for enumerated types).

• The membership relations for Shape can be derived because the type of the component, i.e. Float, is already an instance of those classes.

Page 7: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.7

Recursive algebraic typesdata IntTree = Empty | Node Int IntTree IntTree

sumTree :: IntTree -> IntsumTree Empty = 0sumTree (Node n t1 t2) = n + sumTree t1 + sumTree t2

depth :: IntTree -> Int depth Empty = 0depth (Node n t1 t2) = 1 + max (depth t1) (depth t2)

occurs :: IntTree -> Int -> Intoccurs Empty x = 0occurs (Node n t1 t2) x

| n==x = 1 + occurs t1 x + occurs t2 x| otherwise = occurs t1 x + occurs t2 x

inTree :: Int -> IntTree -> BoolinTree x Empty = FalseinTree x (Node n t1 t2) = n==x || x `inTree` t1 || x `inTree` t2

Page 8: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.8

Recursive algebraic types (cont’d)foldIntTree :: (Int -> a -> a -> a) -> a -> IntTree -> a

foldIntTree f x Empty = x

foldIntTree f x (Node n t1 t2) = f n (foldIntTree f x t1) (foldIntTree f x t2)

sumTree = foldIntTree (\n m p -> n + m + p) 0

depth = foldIntTree (\_ m p -> 1 + max m p) 0

occurs t x = foldIntTree (\n m p -> (if n==x then 1 else 0) + m + p) 0 t

inTree x = foldIntTree (\n b1 b2 -> n==x || b1 || b2) False

Mutual recursion

data Person = Adult Name Address Biog

| Child Name

data Biog= Parent String [Person]

| NonParent String

Page 9: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.9

Example

data Expr= Lit Int

| Expr :+: Expr

| Expr :-: Expr

deriving (Eq)

instance Show Expr where

show (Lit n) = show n

show (e1 :+: e2) = "(" ++ show e1 ++ "+" ++ show e2 ++")"

show (e1 :-: e2) = "(" ++ show e1 ++ "-" ++ show e2 ++")"

eval :: Expr -> Int

eval (Lit n) = n

eval (e1 :+: e2) = eval e1 + eval e2

eval (e1 :-: e2) = eval e1 - eval e2

Page 10: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.10

Polymorphic algebraic typesdata Tree a = Empty | Node a (Tree a) (Tree a)

foldTree :: (a -> b -> b -> b) -> b -> Tree a -> bfoldTree f x Empty = xfoldTree f x (Node y t1 t2) = f y (foldTree f x t1) (foldTree f x t2)

sumTree :: Tree Int -> IntsumTree = foldTree (\n m p -> n + m + p) 0

depth :: Tree a -> Intdepth = foldTree (\_ m p -> 1 + max m p) 0

occurs :: Eq a => a -> Tree a -> Intoccurs x = foldTree (\y m p -> (if x==y then 1 else 0) + m + p) 0

inTree :: Eq a => a -> Tree a -> BoolinTree x = foldTree (\y b1 b2 -> x==y || b1 || b2) False

mapTree :: (a -> b) -> Tree a -> Tree bmapTree f Empty = EmptymapTree f (Node x t1 t2) = Node (f x) (mapTree f t1) (mapTree f t2)

Page 11: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.11

Union typedata Either a b = Left a | Right b

deriving (Eq, Ord, Read, Show)

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

either l r (Left x) = l x

either l r (Right y) = r y

Either a b c

a

b

l

r

Page 12: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.12

Error type

errDiv :: Int -> Int -> InterrDiv n m

| m /= 0 = n `div` m| otherwise = error ”Division by zero”

Here, a division by 0 results in an error message and the program is

terminated.

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

errDiv :: Int -> Int -> Maybe InterrDiv n m

| m /= 0 = Just (n `div` m)| otherwise = Nothing

Page 13: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.13

Error type (cont’d)

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

mapMaybe g Nothing = Nothing

mapMaybe g (Just x) = g x

Maybe a

a g

Maybe b

b

Page 14: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.14

Error type (cont’d)

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

maybe n f Nothing = n

maybe n f (Just x) = f x

Maybe a

a f

b

n

Page 15: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.15

Case study: Huffman codes

Trees can be used to code and decode messages. Consider the tree:

code b = RL

a

b t

Page 16: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.16

Huffman codes (cont’d)Decoding: RLLRR

decode RLLRR = bat

a

b t

a

b t

a

b t

a

b t

a

b t

a

b t

a

b t

a

b t

Page 17: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.17

Huffman codes (cont’d)

code battat = RLLRRRRLRR (10 bits)

code battat = RRRLLLRLL (9 bits)

t

a b

Page 18: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.18

Types.lhs The types used in the Huffman coding example.

(c) Simon Thompson, 1995, 1998

The interface to the module Types is written outexplicitly here, after the module name.

> module Types ( Tree(Leaf,Node), Bit(L,R), > HCode , Table ) where

Trees to represent the relative frequencies of characters and therefore the Huffman codes.

> data Tree = Leaf Char Int | Node Int Tree Tree

The types of bits, Huffman codes and tables of Huffman codes.

> data Bit = L | R deriving (Eq,Show)

> type HCode = [Bit]

> type Table = [ (Char,HCode) ]

Page 19: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.19

Frequency.lhs

Calculating the frequencies of words in a text, used in

Huffman coding.

(c) Simon Thompson, 1995, 1998.

> module Frequency ( frequency ) where

Calculate the frequencies of characters in a list.

This is done by sorting, then counting the number ofrepetitions. The counting is made part of the merge operation in a merge sort.

> frequency :: [Char] -> [ (Char,Int) ]

> frequency> = mergeSort freqMerge . mergeSort alphaMerge . map start> where> start ch = (ch,1)

Page 20: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.20

Merge sort parametrised on the merge operation. This is moregeneral than parametrising on the ordering operation, sinceit permits amalgamation of elements with equal keysfor instance. > mergeSort :: ([a]->[a]->[a]) -> [a] -> [a]

> mergeSort merge xs> | length xs < 2 = xs> | otherwise> = merge (mergeSort merge first)> (mergeSort merge second)> where> first = take half xs> second = drop half xs> half = (length xs) `div` 2

Order on first entry of pairs, withaccumulation of the numeric entries when equal first entry.

> alphaMerge :: [(Char,Int)] -> [(Char,Int)] -> [(Char,Int)]

> alphaMerge xs [] = xs> alphaMerge [] ys = ys> alphaMerge ((p,n):xs) ((q,m):ys)> | (p==q) = (p,n+m) : alphaMerge xs ys> | (p<q) = (p,n) : alphaMerge xs ((q,m):ys)> | otherwise = (q,m) : alphaMerge ((p,n):xs) ys

Page 21: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.21

Lexicographic ordering, second field more significant.

> freqMerge :: [(Char,Int)] -> [(Char,Int)] -> [(Char,Int)]

> freqMerge xs [] = xs> freqMerge [] ys = ys> freqMerge ((p,n):xs) ((q,m):ys)> | (n<m || (n==m && p<q)) > = (p,n) : freqMerge xs ((q,m):ys)> | otherwise > = (q,m) : freqMerge ((p,n):xs) ys

Page 22: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.22

makeTree.lhs

Turn a frequency table into a Huffman tree

(c) Simon Thompson, 1995.

> module MakeTree ( makeTree ) where

> import Types ( Tree(Leaf,Node), Bit(L,R), HCode, Table )

Convert the trees to a list, then amalgamate into a singletree.

> makeTree :: [ (Char,Int) ] -> Tree

> makeTree = makeCodes . toTreeList

Huffman codes are created bottom up: look for the leasttwo frequent letters, make these a new "isAlpha" (i.e. tree)and repeat until one tree formed.

The function toTreeList makes the initial data structure.

> toTreeList :: [ (Char,Int) ] -> [ Tree ]

> toTreeList = map (uncurry Leaf)

Page 23: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.23

The value of a tree.

> value :: Tree -> Int

> value (Leaf _ n) = n> value (Node n _ _) = n

Pair two trees.

> pair :: Tree -> Tree -> Tree

> pair t1 t2 = Node (v1+v2) t1 t2> where> v1 = value t1> v2 = value t2

Insert a tree in a list of trees sorted by ascending value.

> insTree :: Tree -> [Tree] -> [Tree]

> insTree t [] = [t]> insTree t (t1:ts) > | (value t <= value t1) = t:t1:ts> | otherwise = t1 : insTree t ts

Page 24: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.24

Amalgamate the front two elements of the list of trees.

> amalgamate :: [ Tree ] -> [ Tree ]

> amalgamate ( t1 : t2 : ts )> = insTree (pair t1 t2) ts

Make codes: amalgamate the whole list.

> makeCodes :: [Tree] -> Tree

> makeCodes [t] = t> makeCodes ts = makeCodes (amalgamate ts)

Page 25: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.25

codeTable.lhs

Converting a Huffman tree to a ord table.

(c) Simon Thompson, 1995, 1998.

> module CodeTable ( codeTable ) where

> import Types ( Tree(Leaf,Node), Bit(L,R), HCode, Table )

Making a table from a Huffman tree.

> codeTable :: Tree -> Table

> codeTable = convert []

Auxiliary function used in conversion to a table. The first argument isthe HCode which codes the path in the tree to the current Node, and socodeTable is initialised with an empty such sequence.

> convert :: HCode -> Tree -> Table

> convert cd (Leaf c n) = [(c,cd)]> convert cd (Node n t1 t2)> = (convert (cd++[L]) t1) ++ (convert (cd++[R]) t2)

Page 26: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.26

Show functions^^^^^^^^^^^^^^

Show a tree, using indentation to show structure.

> showTree :: Tree -> String

> showTree t = showTreeIndent 0 t

The auxiliary function showTreeIndent has a second, current level of indentation, as a parameter.

> showTreeIndent :: Int -> Tree -> String

> showTreeIndent m (Leaf c n) > = spaces m ++ show c ++ " " ++ show n ++ "\n"> showTreeIndent m (Node n t1 t2)> = showTreeIndent (m+4) t1 ++> spaces m ++ "[" ++ show n ++ "]" ++ "\n" ++> showTreeIndent (m+4) t2

A String of n spaces.

> spaces :: Int -> String

> spaces n = replicate n ' '

Page 27: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.27

To show a sequence of Bits.

> showCode :: HCode -> String> showCode = map conv> where> conv R = 'R'> conv L = 'L'

To show a table of codes.

> showTable :: Table -> String

> showTable > = concat . map showPair> where> showPair (ch,co) = [ch] ++ " " ++ showCode co ++ "\n"

Page 28: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.28

Coding.lhs

Huffman coding in Haskell. The top-level functions for coding and decoding.

(c) Simon Thompson, 1995.

> module Coding ( codeMessage , decodeMessage ) where

> import Types ( Tree(Leaf,Node), Bit(L,R), HCode, Table )

Code a message according to a table of codes.

> codeMessage :: Table -> [Char] -> HCode

> codeMessage tbl = concat . map (lookupTable tbl)

lookupTable looks up the meaning of an individual char ina Table.

> lookupTable :: Table -> Char -> HCode

> lookupTable [] c = error "lookupTable"> lookupTable ((ch,n):tb) c> | (ch==c) = n> | otherwise = lookupTable tb c

Page 29: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.29

Decode a message according to a tree.

The first tree arguent is constant, being the tree of codes;the second represents the current position in the tree relativeto the (partial) HCode read so far.

> decodeMessage :: Tree -> HCode -> String

> decodeMessage tr> = decodeByt tr> where> > decodeByt (Node n t1 t2) (L:rest)> = decodeByt t1 rest> > decodeByt (Node n t1 t2) (R:rest)> = decodeByt t2 rest> > decodeByt (Leaf c n) rest> = c : decodeByt tr rest> > decodeByt t [] = []

Page 30: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.30

MakeCode.lhs

Huffman coding in Haskell.

(c) Simon Thompson, 1995, 1998.

> module MakeCode ( codes, codeTable ) where

> import Types> import Frequency ( frequency )> import MakeTree ( makeTree )> import CodeTable ( codeTable )

Putting together frequency calculation and tree conversion

> codes :: [Char] -> Tree

> codes = makeTree . frequency

Page 31: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.31

Main.lhs

The main module of the Huffman example

(c) Simon Thompson, 1995,1998.

The main module of the Huffman example

> module Main (main) where

> import Types ( Tree(Leaf,Node), Bit(L,R), HCode , Table )> import Coding ( codeMessage, decodeMessage ) > import MakeCode ( codes, codeTable )

> main = print decoded

Examples^^^^^^^^

The coding table generated from the text "there is a green hill".

> tableEx :: Table> tableEx = codeTable (codes "there is a green hill")

Page 32: © M. Winter COSC 4P41 – Functional Programming 6.16.1 Enumerated types data Temp = Cold | Hot data Season= Spring | Summer | Autumn | Winter weather ::

© M. Winter

COSC 4P41 – Functional Programming

6.32

The Huffman tree generated from the text "there is a green hill",from which tableEx is produced by applying codeTable.

> treeEx :: Tree> treeEx = codes "there is a green hill"

A message to be coded.

> message :: String> message = "there are green hills here"

The message in code.

> coded :: HCode> coded = codeMessage tableEx message

The coded message decoded.

> decoded :: String> decoded = decodeMessage treeEx coded