Download Week 6

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
COSC 4P41 – Functional Programming
Enumerated types
data Temp
data Season
= Cold | Hot
= 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
© M. Winter
6.1
COSC 4P41 – Functional Programming
Product types
type Name
type Age
= String
= Int
data People
= Person Name Age
Examples values of type People:
Person ”Electric Aunt Jemima” 77
Person ”Ronnie” 14
Person :: Name -> Age -> People
© M. Winter
6.2
COSC 4P41 – Functional Programming
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.
© M. Winter
6.3
COSC 4P41 – Functional Programming
Alternatives
data Shape
= Circle Float
| Rectangle Float Float
isRound :: Shape -> Bool
isRound (Circle _)
isRound (Rectangle _ _)
= True
= False
area :: Shape -> Float
area (Circle r)
area (Rectangle h w)
= pi*r*r
= h*w
Circle :: Float -> Shape
Rectangle :: Float -> Float -> Shape
© M. Winter
6.4
COSC 4P41 – Functional Programming
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
© M. Winter
6.5
COSC 4P41 – Functional Programming
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.
© M. Winter
6.6
COSC 4P41 – Functional Programming
Recursive algebraic types
data IntTree
= Empty | Node Int IntTree IntTree
sumTree :: IntTree -> Int
sumTree Empty
= 0
sumTree (Node n t1 t2) = n + sumTree t1 + sumTree t2
depth :: IntTree -> Int
depth Empty
= 0
depth (Node n t1 t2) = 1 + max (depth t1) (depth t2)
occurs :: IntTree -> Int -> Int
occurs Empty x
= 0
occurs (Node n t1 t2) x
| n==x
= 1 + occurs t1 x + occurs t2 x
| otherwise
=
occurs t1 x + occurs t2 x
inTree :: Int -> IntTree -> Bool
inTree x Empty
= False
inTree x (Node n t1 t2) = n==x || x `inTree` t1 || x `inTree` t2
© M. Winter
6.7
COSC 4P41 – Functional Programming
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
depth
occurs t x
inTree x
=
=
=
=
foldIntTree
foldIntTree
foldIntTree
foldIntTree
(\n
(\_
(\n
(\n
m p -> n + m + p) 0
m p -> 1 + max m p) 0
m p -> (if n==x then 1 else 0) + m + p) 0 t
b1 b2 -> n==x || b1 || b2) False
Mutual recursion
data Person
= Adult Name Address Biog
| Child Name
data Biog
= Parent String [Person]
| NonParent String
© M. Winter
6.8
COSC 4P41 – Functional Programming
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
eval
eval
eval
:: Expr -> Int
(Lit n)
= n
(e1 :+: e2)
= eval e1 + eval e2
(e1 :-: e2)
= eval e1 - eval e2
© M. Winter
6.9
COSC 4P41 – Functional Programming
Polymorphic algebraic types
data Tree a
= Empty | Node a (Tree a) (Tree a)
foldTree :: (a -> b -> b -> b) -> b -> Tree a -> b
foldTree f x Empty
= x
foldTree f x (Node y t1 t2) = f y (foldTree f x t1) (foldTree f x t2)
sumTree :: Tree Int -> Int
sumTree
= foldTree (\n m p -> n + m + p) 0
depth :: Tree a -> Int
depth
= foldTree (\_ m p -> 1 + max m p) 0
occurs :: Eq a => a -> Tree a -> Int
occurs x
= foldTree (\y m p -> (if x==y then 1 else 0) + m + p) 0
inTree :: Eq a => a -> Tree a -> Bool
inTree x
= foldTree (\y b1 b2 -> x==y || b1 || b2) False
mapTree :: (a -> b) -> Tree a -> Tree b
mapTree f Empty
= Empty
mapTree f (Node x t1 t2) = Node (f x) (mapTree f t1) (mapTree f t2)
© M. Winter
6.10
COSC 4P41 – Functional Programming
Union type
data 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
a
b
© M. Winter
c
l
r
6.11
COSC 4P41 – Functional Programming
Error type
errDiv :: Int -> Int -> Int
errDiv 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 Int
errDiv n m
| m /= 0
= Just (n `div` m)
| otherwise
= Nothing
© M. Winter
6.12
COSC 4P41 – Functional Programming
Error type (cont’d)
mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe g Nothing = Nothing
mapMaybe g (Just x) = g x
Maybe a
a
© M. Winter
Maybe b
g
b
6.13
COSC 4P41 – Functional Programming
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
b
f
n
© M. Winter
6.14
COSC 4P41 – Functional Programming
Case study: Huffman codes
Trees can be used to code and decode messages. Consider the tree:
a
b
t
code b = RL
© M. Winter
6.15
COSC 4P41 – Functional Programming
Huffman codes (cont’d)
Decoding: RLLRR
a
a
b
a
b
t
a
b
t
a
b
t
a
b
t
a
b
t
t
a
b
t
b
t
decode RLLRR = bat
© M. Winter
6.16
COSC 4P41 – Functional Programming
Huffman codes (cont’d)
code battat = RLLRRRRLRR (10 bits)
t
a
b
code battat = RRRLLLRLL (9 bits)
© M. Winter
6.17
COSC 4P41 – Functional Programming
Types.lhs
The types used in the Huffman coding example.
(c) Simon Thompson, 1995, 1998
The interface to the module Types is written out
explicitly 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) ]
© M. Winter
6.18
COSC 4P41 – Functional Programming
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 of
repetitions. 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)
© M. Winter
6.19
COSC 4P41 – Functional Programming
Merge sort parametrised on the merge operation. This is more
general than parametrising on the ordering operation, since
it permits amalgamation of elements with equal keys
for 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, with
accumulation 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
© M. Winter
6.20
COSC 4P41 – Functional Programming
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
© M. Winter
6.21
COSC 4P41 – Functional Programming
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 single
tree.
>
makeTree :: [ (Char,Int) ] -> Tree
>
makeTree = makeCodes . toTreeList
Huffman codes are created bottom up: look for the least
two 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)
© M. Winter
6.22
COSC 4P41 – Functional Programming
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)
| otherwise
© M. Winter
= t:t1:ts
= t1 : insTree t ts
6.23
COSC 4P41 – Functional Programming
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)
© M. Winter
6.24
COSC 4P41 – Functional Programming
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 is
the HCode which codes the path in the tree to the current Node, and so
codeTable 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)
© M. Winter
6.25
COSC 4P41 – Functional Programming
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 ++ "
showTreeIndent m (Node n t1
= showTreeIndent (m+4) t1
spaces m ++ "[" ++ show
showTreeIndent (m+4) t2
" ++ show n ++ "\n"
t2)
++
n ++ "]" ++ "\n" ++
A String of n spaces.
>
spaces :: Int -> String
>
spaces n = replicate n ' '
© M. Winter
6.26
COSC 4P41 – Functional Programming
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
>
>
>
>
© M. Winter
showTable
= concat . map showPair
where
showPair (ch,co) = [ch] ++ " " ++ showCode co ++ "\n"
6.27
COSC 4P41 – Functional Programming
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 in
a Table.
>
lookupTable :: Table -> Char -> HCode
>
>
>
>
lookupTable [] c = error "lookupTable"
lookupTable ((ch,n):tb) c
| (ch==c)
= n
| otherwise
= lookupTable tb c
© M. Winter
6.28
COSC 4P41 – Functional Programming
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 relative
to the (partial) HCode read so far.
>
decodeMessage :: Tree -> HCode -> String
>
>
>
>
>
>
>
>
>
>
>
>
>
>
decodeMessage tr
= decodeByt tr
where
© M. Winter
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 [] = []
6.29
COSC 4P41 – Functional Programming
MakeCode.lhs
Huffman coding in Haskell.
(c) Simon Thompson, 1995, 1998.
>
module MakeCode ( codes, codeTable ) where
>
>
>
>
import
import
import
import
Types
Frequency ( frequency )
MakeTree ( makeTree )
CodeTable ( codeTable )
Putting together frequency calculation and tree conversion
>
codes :: [Char] -> Tree
>
codes = makeTree . frequency
© M. Winter
6.30
COSC 4P41 – Functional Programming
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")
© M. Winter
6.31
COSC 4P41 – Functional Programming
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
© M. Winter
6.32
Related documents