Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
COSC 4P41 – Functional Programming Modules in Haskell Using modules to structure a large program has a number of advantages: • Parts of the system can be built separately from each other. • Parts of the system can be compiled separately. • Libraries of components can be reused, by importing the appropriate module containing them. module Ant where type Ants = … antEater x = … The convention for file names is that a module Ant resides in the Haskell file Ant.hs or Ant.lhs. © M. Winter 5.1 COSC 4P41 – Functional Programming Importing a module module Bee where import Ant beeKeeper = … Importing the module Ant means that the visible definitions from the module can be used in Bee. By default the visible definitions in a module are those which appear in the module itself. module Cow where import Bee The definitions of Ant are not visible in Cow. © M. Winter 5.2 COSC 4P41 – Functional Programming Export control We can control what is exported by following the name of the module with a list of what is to be exported. • module Bee (beeKeeper, Ants, antEater) where … • module Bee (beeKeeper, module Ant) where … • module Fish where type Fish = (String,Size) • module Fish (Fish(..),…) where newtype Fish = F (String,Size) • module Fish (Fish,…) where newtype Fish = F (String,Size) © M. Winter 5.3 COSC 4P41 – Functional Programming Import control Examples: • import Ant (Ants) • import Ant hiding (antEater) • module Bear where import qualified Ant antEater x = … Ant.antEater x … • import Insect as Ant • import Prelude hiding (words) • import qualified Prelude © M. Winter 5.4 COSC 4P41 – Functional Programming Overloading and type classes A polymorphic function such as length has a single definition which works over all its types. length :: [a] -> Int length = foldl' (\n _ -> n + 1) 0 An overloaded function like equality (==), + and show can be used at a variety of types, but with different definitions being used at different types. © M. Winter 5.5 COSC 4P41 – Functional Programming Why overloading? elemBool :: Bool -> [Bool] -> Bool elemBool x [] = False elemBool x (y:ys) = (x ==Bool y) || elemBool x ys elemInt :: Int -> [Int] -> Bool elemInt x [] = False elemInt x (y:ys) = (x ==Int y) || elemInt x ys Generalization may lead to the definition: elemGen :: (a -> a -> Bool) -> a -> [a] -> Bool elemGen p x [] = False elemGen p x (y:ys) = p x y || elemGen x ys but this is too general in a sense, because it can be used with any parameter of type a -> a -> Bool rather than just an equality check. © M. Winter 5.6 COSC 4P41 – Functional Programming Why overloading? (cont’d) Generalization in the following way will not work. The definition elem :: a -> [a] -> Bool elem x [] = False elem x (y:ys) = (x == y) || elem x ys will cause an error No instance for (Eq a) arising from a use of `==' In the first argument of `(||)', namely `x == y' In the expression: x == y || elem x ys In an equation for `elem`: elem x (y : ys) = x == y || elem x ys because this definition requires that (==) :: a -> a -> Bool is already defined. © M. Winter 5.7 COSC 4P41 – Functional Programming Classes A type class or simply a class defines a collection of types over which specific functions are defined. class Eq a where (==) :: a -> a -> Bool Members of a class are called instances. Built-in instances of Eq include the base types Int, Float, Bool, Char, tuples and lists built from types which are themselves instances of Eq, e.g., (Int,Bool) and [[Char]]. elem :: Eq a => a -> [a] -> Bool elem x [] = False elem x (y:ys) = (x == y) || elem x ys © M. Winter 5.8 COSC 4P41 – Functional Programming Classes (cont’d) (+1) :: Int -> Int elem (+1) [] causes an error No instance for (Eq (a0 -> a0)) arising from a use of `elem' Possible fix: add an instance declaration for (Eq (a0 -> a0)) In the expression: elem (+ 1) [] In an equation for `it': it = elem (+ 1) [] which conveys the fact that Int -> Int is not an instance of the Eq class. © M. Winter 5.9 COSC 4P41 – Functional Programming Instances of classes Examples: instance True False _ Eq == == == Bool where True = True False = True _ = False instance Eq a [] == (x:xs) == _ == => Eq [a] [] = (y:ys) = _ = where True x==y && xs==ys False instance (Eq a, Eq b) => Eq (a,b) where (x,y) == (z,w) = x==z && y==w © M. Winter 5.10 COSC 4P41 – Functional Programming Default definitions The Haskell Eq class is in fact defined by class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x==y) x == y = not (x/=y) Both functions have default definitions in terms of the other function. At any instance a definition of at least one of == and /= needs to be provided. © M. Winter 5.11 COSC 4P41 – Functional Programming Derived classes To be ordered, a type must carry operations >, >= and so on, as well as the equality operations. class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a © M. Winter 5.12 COSC 4P41 – Functional Programming Example class Visible a where toString :: a -> String size :: a -> Int instance Visible Bool toString True = toString False = size _ = where ”True” ”False” 1 instance Visible a => Visible [a] where toString = concat . map toString size = foldr (+) 1 . map size © M. Winter 5.13 COSC 4P41 – Functional Programming Example (cont’d) sort :: Ord a => [a] -> [a] vSort :: (Ord a, Visible a) => [a] -> String vSort = toString . sort class (Ord a, Visible a) => OrdVis a vSort' :: OrdVis a => [a] -> String vSort' = toString . sort © M. Winter 5.14 COSC 4P41 – Functional Programming A tour of the built-in Haskell classes Many of the Haskell built-in classes are numeric, and are built to deal with overloading of the numerical operations. We will not study those classes. Class Eq: class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x==y) x == y = not (x/=y) Instances: All except of IO, -> © M. Winter 5.15 COSC 4P41 – Functional Programming Class Ord class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a -- Minimal complete definition: (<=) or compare -- using compare can be more efficient for complex types compare x y | x==y = EQ | x<=y = LT | otherwise = GT x <= y = compare x y /= GT x < y = compare x y == LT x >= y = compare x y /= LT x > y = compare x y == GT max x y | x <= y = y | otherwise = x min x y | x <= y = x | otherwise = y Instances: All except IO, IOError, -> © M. Winter 5.16 COSC 4P41 – Functional Programming Class Enum class Enum a where succ, pred toEnum fromEnum enumFrom enumFromThen enumFromTo enumFromThenTo :: :: :: :: :: :: :: a -> a Int -> a a -> Int a -> [a] a -> a -> [a] a -> a -> [a] a -> a -> a -> [a] ----- [n..] [n,m..] [n..m] [n,n'..m] -- Minimal complete definition: toEnum, fromEnum succ = toEnum . (1+) . fromEnum pred = toEnum . subtract 1 . fromEnum enumFrom x = map toEnum [ fromEnum x ..] enumFromTo x y = map toEnum [ fromEnum x .. fromEnum y ] enumFromThen x y = map toEnum [ fromEnum x, fromEnum y ..] enumFromThenTo x y z = map toEnum [ fromEnum x, fromEnum y .. fromEnum z ] Instances: (), Bool, Char, Int, Integer, Float Double © M. Winter 5.17 COSC 4P41 – Functional Programming Class Bounded class Bounded a where minBound, maxBound :: a -- Minimal complete definition: All Instances: Int, Char, Bool (but not Integer) © M. Winter 5.18 COSC 4P41 – Functional Programming Class Show type ShowS = String -> String class Show a where show :: a -> String showsPrec :: Int -> a -> ShowS showList :: [a] -> ShowS -- Minimal complete definition: show or showsPrec show x = showsPrec 0 x "" showsPrec _ x s = show x ++ s showList [] = showString "[]" showList (x:xs) = showChar '[' . shows x . showl xs where showl [] = showChar ']' showl (x:xs) = showChar ',' . shows x . showl xs Instances: All except -> © M. Winter 5.19 COSC 4P41 – Functional Programming Class Read type ReadS a = String -> [(a,String)] class Read a where readsPrec :: Int -> ReadS a readList :: ReadS [a] -- Minimal complete definition: readsPrec readList = readParen False (\r -> [pr | ("[",s) <- lex r, pr <- readl s ]) where readl s = [([],t) | ("]",t) <- lex s] ++ [(x:xs,u) | (x,t) <- reads s, (xs,u) <- readl' t] readl' s = [([],t) | ("]",t) <- lex s] ++ [(x:xs,v) | (",",t) <- lex s, (x,u) <- reads t, (xs,v) <- readl' u] Instances: All except IO, -> © M. Winter 5.20