KEMBAR78
06. haskell type builder | ODP
Type-Builder

               Sebastian Rettig


In 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 won't 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
Let's 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, let's 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

    ?
Let's 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 want's 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
Implement Membership



  Next Session :)
Sources
[1] Haskell-Tutorial: Learn you a Haskell (http://learnyouahaskell.com/,
    2012/03/15)
[2] The Hugs User-Manual (
    http://cvs.haskell.org/Hugs/pages/hugsman/index.html, 2012/03/15)
[3] The Haskellwiki (http://www.haskell.org/haskellwiki, 2012/03/15)

06. haskell type builder

  • 1.
    Type-Builder Sebastian Rettig In 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.
  • 2.
    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)
  • 3.
    Haskell Features ● Pure Functional Programming Language ● Lazy Evaluation ● Pattern Matching and Guards ● List Comprehension ● Type Polymorphism
  • 4.
    Static Type System ● type of every expression is known at compile time – use operation with not compatible types – → program won't compile – → saver code
  • 5.
    Nice to remember(1) ● Types: – starts with uppercase letter – e.g.: ● Bool ● Int ● String ● [Int] ● (Bool, Char) ● Integer
  • 6.
    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)
  • 7.
    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
  • 8.
    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"
  • 9.
    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?
  • 10.
    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>
  • 11.
    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'])
  • 12.
    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
  • 13.
    Let's build owntypes ● first look how existing types are defined: – data Bool = False | True ● data keyword is used to define a type ● Bool is the type ● okay, let's define one, e.g.: – data TrafficLight = Red | Yellow | Green
  • 14.
    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 ?
  • 15.
    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 ?
  • 16.
    Let's use ourtype ● 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
  • 17.
    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
  • 18.
    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
  • 19.
    Membership of aTypeclass ● What happens? – GHCi want's 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
  • 20.
    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
  • 21.
    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
  • 22.
    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
  • 23.
    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
  • 24.
    Implement Membership Next Session :)
  • 25.
    Sources [1] Haskell-Tutorial: Learnyou a Haskell (http://learnyouahaskell.com/, 2012/03/15) [2] The Hugs User-Manual ( http://cvs.haskell.org/Hugs/pages/hugsman/index.html, 2012/03/15) [3] The Haskellwiki (http://www.haskell.org/haskellwiki, 2012/03/15)