Type-Builder Sebastian RettigIn Haskell normally you understand aa function by reading In Haskell normally you understand function by reading Function Name ++ Parameter Types++Result Type. Function Name Parameter Types Result Type.
Functional Programming● No Variables● Functions only, eventually stored in Modules – Behavior do not change, once defined – → Function called with same parameter calculates always the same result● Function definitions (Match Cases)● Recursion (Memory)
Haskell Features● Pure Functional Programming Language● Lazy Evaluation● Pattern Matching and Guards● List Comprehension● Type Polymorphism
Static Type System● type of every expression is known at compile time – use operation with not compatible types – → program wont compile – → saver code
Nice to remember (1)● Types: – starts with uppercase letter – e.g.: ● Bool ● Int ● String ● [Int] ● (Bool, Char) ● Integer
Nice to remember (2)● Typevariables – to define generic types – e.g.: ● maxList :: [a] -> a ● fst :: (a,b) -> a ● snd :: (a,b) -> b – Typevariables a and b can contain every type (including the same type)
Nice to remember (3)● GHCi Commands (Interpreter): – :t ← returns the function header (type) – :t tail tail :: [a] -> [a] – :t 2 == 4 2 == 4 :: Bool – :t "HELLO!" "HELLO!" :: [Char] – :i ← returns the function definition (interface) – :i tail tail :: [a] -> [a] -- Defined in GHC.List
Type Polymorphism (1)● Statically typed, but Compiler can read type from context (type inference)● → no need to set type explicitly (but preferred!)● → makes function more generic for different kinds of types (type polymorphism) – Why should I use quicksort :: [Int] -> [Int] – even if I also want to sort character? Hugs> quicksort [f,a,d,b] "abdf"
Type Polymorphism (2)● the header could be fact :: Int -> Int maxList :: [Int] -> Int● but is only limited to Int, but maxList could also handle Char● → why not make it generic? maxList :: [a] -> a● but what happens, if the corresponding Type is not comparable or cannot be ordered?
Type Polymorphism (3)● Solution: use Typeclasses maxList :: (Ord a) => [a] -> a● then we can be sure to use (<,<=, ==, /=, >=, >)● function header can contain multiple typeclasses maxList :: (Ord a, Eq b) => [a] -> [b] -> a● In Haskell-Interpreter: to list the function header :t <function_name>
Typeclasses (1)● define properties of the types● like an interface● Typeclasses: – Eq can be compared – Ord can be ordered (>, <, >=, <=) (extending Eq) – Show can be shown as string – Read opposite of Show – Enum sequentially ordered types (can be enumerated and usable in List-Ranges [a..e])
Typeclasses (2)● Typeclasses: – Bounded upper/lower bound (minBound, maxBound) – Num types behave like numbers (must already be Show, Eq) – Integral contains only integrals (subclass of Num) – Floating corresponding real numbers (subclass of Num)● if all Types of tuple are in same Typeclass → Tuple also in Typeclass
Lets build own types● first look how existing types are defined: – data Bool = False | True● data keyword is used to define a type● Bool is the type● okay, lets define one, e.g.: – data TrafficLight = Red | Yellow | Green
Value Constructors (1)● or a more complex one, e.g.: – data Shape = Circle Float Float Float | Rectangle Float Float Float Float● Circle and Rectangle are Value Constructors● can contain types which holds the specific values● Question: What is Red, Yellow, Green in – data TrafficLight = Red | Yellow | Green ?
Value Constructors (2)● Value Constructors are just functions which: – get parameters of a specific type – and returns the defined type● → you can do: :t Circle Circle :: Float -> Float -> Float -> Shape● to look at the Type definition , you can use: :i Shape● Question: What is the result of: :t Red in data TrafficLight = Red | Yellow | Green ?
Lets use our type● e.g.: calculate the surface of a Shape surface :: Shape -> Float surface (Circle _ _ r) = pi * r ^ 2 surface (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)● → and call it: Main> surface (Circle 1 2 3) 28.274334● sometimes the parenthesis are annoying → better readability with $ surface $ Circle 1 2 3
Type Handling● Why not just use (Float, Float, Float)? – can define everything (e.g.: vector) → no context – needs two functions, one for Circle and one for Rectangle● in Haskell normally you understand a function by reading – function name + parameter types + result type● → you should write explicitly the function header● → except for really small functions
Another Function● e.g.: move left a Shape moveLeft :: Shape -> Float -> Shape moveLeft (Circle x y r) m = (Circle (x-m) y r) moveLeft (Rectangle x1 y1 x2 y2) m = (Rectangle (x1-m) y1 (x2-m) y2)● → and call it: Main> moveLeft (Circle 1 2 3) 2 No instance for (Show Shape) arising from a use of `print Possible fix: add an instance declaration for (Show Shape) In a stmt of an interactive GHCi command: print it
Membership of a Typeclass● What happens? – GHCi wants to print out (String) the result – the Typeclass Show converts a type to String● → Type must be part of the Typeclass Show● two ways to solve this: – inherit from existing implementation of types you use – implement the specific typeclass functions by yourself
Inherit Membership (1)● If used types are already member of the Typeclass – Haskell use the implementation of this types to print the specific values – Value Constructor can generally be printed out – you only need to derive from the Implementation
Inherit Membership (2)● first check if Float has already a membership: data Float = GHC.Types.F# GHC.Prim.Float# -- Defined in GHC.Types … instance Show Float -- Defined in GHC.Float …● okay, then we can use the deriving keyword data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show)● and call again: moveLeft (Circle 1 2 3) 2 Circle (-1.0) 2.0 3.0
Inherit Membership (3)● Float has also membership of Typeclass Ord: instance Ord Float -- Defined in GHC.Classes instance Eq Float -- Defined in GHC.Classes● we can also derive from Ord but also from Eq data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show, Eq, Ord)● and we can use: maxList :: (Ord a) => [a] -> a maxList [(Circle 1 2 3), (Circle 2 3 4)] – returns: Circle 2.0 3.0 4.0
Inherit Membership (4)● to check our new Typeclass memberships: data Shape = Circle Float Float Float | Rectangle Float Float Float Float -- Defined at type.hs:3:6-10 instance Eq Shape -- Defined at type.hs:3:91-92 instance Ord Shape -- Defined at type.hs:3:95-97 instance Show Shape -- Defined at type.hs:3:85-88
Sources Haskell-Tutorial: Learn you a Haskell (http://learnyouahaskell.com/, 2012/03/15) The Hugs User-Manual ( http://cvs.haskell.org/Hugs/pages/hugsman/index.html, 2012/03/15) The Haskellwiki (http://www.haskell.org/haskellwiki, 2012/03/15)