Membership

               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
Nice to remember (4)
    Typeclasses:
●   define properties of the types
●   like an interface
         –   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'])
Our own Type (1)
●   in the last session, we created the following Type:
    data Shape =
      Circle Float Float Float |
      Rectangle Float Float Float Float
●   and created a function to move 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)
Our own Type (2)
●   → and called it in GHCi and got the following
     Exception:

      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
Remember : Static Type System
●   type of every expression is known at compile time
        –   use operation with not compatible types
        –   → program won't compile
        –   → saver code
●   QUESTION:
            Would this Code compile?
Remember : Static Type System
●   type of every expression is known at compile time
        –   use operation with not compatible types
        –   → program won't compile
        –   → saver code
●   QUESTION:
            Would this Code compile?

                         YES!
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)
●   in the last session, we used the simple way and derived
       the Memberships Show, Eq and Ord from Float Type
       we are using in our Type:
    data Shape =
      Circle Float Float Float |
      Rectangle Float Float Float Float
      deriving (Show, Eq, Ord)
●   and we check our new Typeclass memberships with (:i):
    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
Inherit Membership (2)
●   and we can now use:
    maxList :: (Ord a) => [a] -> a
    maxList [(Circle 1 2 5), (Circle 2 3 4)]
        –   returns: Circle 2.0 3.0 4.0
●   Ord, Eq & Show implementation of Float works
●   BUT: the result is not correct, why?
        –   Ord, Eq Implementation of Float compares only two
              values
        –   the first value, if equal → second, if equal → third
        –   but we need to compare the third value (radius) only
Implement Membership (1)
●   to solve this, we have to implement Ord and Eq by our own
●   first, we have to find the functions of the typeclass to
        implement :
    :i Eq
      class Eq a where
      (==) :: a -> a -> Bool
      (/=) :: a -> a -> Bool
      -- Defined in GHC.Classes
●   if we look in prelude.hs, we can see the implementation of
        these functions
Implement Membership (2)
●   class keyword defines a new typeclass
    class Eq a where
         (==) :: a -> a -> Bool
         (/=) :: a -> a -> Bool
         x == y = not (x /= y)
         x /= y = not (x == y)
●   a is the type variable
●   we have to implement the membership of Eq for our Type
      Shape
Implement Membership (3)
●   instance keyword defines a membership instance
    instance Eq Shape where
    (Circle _ _ r) == (Circle _ _ r')   =   r == r'
    (Rectangle x1 y1 x2 y2) == (Rectangle x1' y1' x2' y2') =
      (x1 - x2) == (x1' - x2') && (y1 - y2) == (y1' - y2')
    _ == _ = False

●   we don't need to implement (/=), why?
Implement Membership (4)
●   and for the Ord Typeclass:
    :i Ord
      class Eq a => Ord a where
      compare :: a -> a -> Ordering
      (<) :: a -> a -> Bool
      (>=) :: a -> a -> Bool
      (>) :: a -> a -> Bool
      (<=) :: a -> a -> Bool
      max :: a -> a -> a
      min :: a -> a -> a
      -- Defined in GHC.Classes
Implement Membership (5)
    instance Ord Shape where
    a <= b = surface a <= surface b
    a >= b = surface a >= surface b
    a < b = not (a >= b)
    a > b = not (a <= b)

●   min, max and compare just use the implemented
      functions
Type Parameters (1)
●   parameter for a type constructor to create new type
●   e.g.: (Maybe for the World)
             data Maybe a = Nothing | Just a
●   type Maybe is used with another type, but don't care about the
       type
●   e.g.: ghci> :t Just "Hey"
       Just "Hey" :: Maybe [Char]
●   Question: What is the result of:
         –   :t Just 6
         –   :t Nothing
Type Parameters (2)
●   type parameter can also contain typeclass cntraints
●   e.g.:
       data (Ord a) => Maybe a = Nothing | Just a
●   BUT please avoid such design!
         –   → every function must use this constraints
         –   → even if the do not ord anything
●   → better to set constraints in every function header, where
      you need the constraint
         –   max :: (Ord a) => a -> a -> a
Record Syntax
●   for a better structure of your type
    data Car = Car { company :: String
                               , model :: String
                               , year :: String

                               } deriving (Show)
●   instead of:
    data Car = Car String String String
      deriving (Show)
Record Syntax (2)
●   to use in code:
    ghci> Car {company="Ford", model="Mustang",
      year=1967}
●   result:
      Car {company = "Ford", model = "Mustang", year =
      1967}
●   can also contain type parameters:
    data Car a b c = Car { company :: a
                             , model :: b
                             , year :: c
                             } deriving (Show)
Type Synonyms
●   alias for a defined type
●   for better reading and context understanding
●   to define Type Synonym, use the type keyword
        –   type String = [Char]
        –   type Name = String
        –   type Phonenumber = String
        –   type Phonebook = [(Name, Phonenumber)]
●   can also contain parameters
        –   type IntMap v = Map Int v
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)

07. haskell Membership

  • 1.
    Membership 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.
    Nice to remember(4) Typeclasses: ● define properties of the types ● like an interface – 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'])
  • 9.
    Our own Type(1) ● in the last session, we created the following Type: data Shape = Circle Float Float Float | Rectangle Float Float Float Float ● and created a function to move 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)
  • 10.
    Our own Type(2) ● → and called it in GHCi and got the following Exception: 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
  • 11.
    Remember : StaticType System ● type of every expression is known at compile time – use operation with not compatible types – → program won't compile – → saver code ● QUESTION: Would this Code compile?
  • 12.
    Remember : StaticType System ● type of every expression is known at compile time – use operation with not compatible types – → program won't compile – → saver code ● QUESTION: Would this Code compile? YES!
  • 13.
    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
  • 14.
    Inherit Membership (1) ● in the last session, we used the simple way and derived the Memberships Show, Eq and Ord from Float Type we are using in our Type: data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show, Eq, Ord) ● and we check our new Typeclass memberships with (:i): 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
  • 15.
    Inherit Membership (2) ● and we can now use: maxList :: (Ord a) => [a] -> a maxList [(Circle 1 2 5), (Circle 2 3 4)] – returns: Circle 2.0 3.0 4.0 ● Ord, Eq & Show implementation of Float works ● BUT: the result is not correct, why? – Ord, Eq Implementation of Float compares only two values – the first value, if equal → second, if equal → third – but we need to compare the third value (radius) only
  • 16.
    Implement Membership (1) ● to solve this, we have to implement Ord and Eq by our own ● first, we have to find the functions of the typeclass to implement : :i Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool -- Defined in GHC.Classes ● if we look in prelude.hs, we can see the implementation of these functions
  • 17.
    Implement Membership (2) ● class keyword defines a new typeclass class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) ● a is the type variable ● we have to implement the membership of Eq for our Type Shape
  • 18.
    Implement Membership (3) ● instance keyword defines a membership instance instance Eq Shape where (Circle _ _ r) == (Circle _ _ r') = r == r' (Rectangle x1 y1 x2 y2) == (Rectangle x1' y1' x2' y2') = (x1 - x2) == (x1' - x2') && (y1 - y2) == (y1' - y2') _ == _ = False ● we don't need to implement (/=), why?
  • 19.
    Implement Membership (4) ● and for the Ord Typeclass: :i Ord class Eq a => Ord a where compare :: a -> a -> Ordering (<) :: a -> a -> Bool (>=) :: a -> a -> Bool (>) :: a -> a -> Bool (<=) :: a -> a -> Bool max :: a -> a -> a min :: a -> a -> a -- Defined in GHC.Classes
  • 20.
    Implement Membership (5) instance Ord Shape where a <= b = surface a <= surface b a >= b = surface a >= surface b a < b = not (a >= b) a > b = not (a <= b) ● min, max and compare just use the implemented functions
  • 21.
    Type Parameters (1) ● parameter for a type constructor to create new type ● e.g.: (Maybe for the World) data Maybe a = Nothing | Just a ● type Maybe is used with another type, but don't care about the type ● e.g.: ghci> :t Just "Hey" Just "Hey" :: Maybe [Char] ● Question: What is the result of: – :t Just 6 – :t Nothing
  • 22.
    Type Parameters (2) ● type parameter can also contain typeclass cntraints ● e.g.: data (Ord a) => Maybe a = Nothing | Just a ● BUT please avoid such design! – → every function must use this constraints – → even if the do not ord anything ● → better to set constraints in every function header, where you need the constraint – max :: (Ord a) => a -> a -> a
  • 23.
    Record Syntax ● for a better structure of your type data Car = Car { company :: String , model :: String , year :: String } deriving (Show) ● instead of: data Car = Car String String String deriving (Show)
  • 24.
    Record Syntax (2) ● to use in code: ghci> Car {company="Ford", model="Mustang", year=1967} ● result: Car {company = "Ford", model = "Mustang", year = 1967} ● can also contain type parameters: data Car a b c = Car { company :: a , model :: b , year :: c } deriving (Show)
  • 25.
    Type Synonyms ● alias for a defined type ● for better reading and context understanding ● to define Type Synonym, use the type keyword – type String = [Char] – type Name = String – type Phonenumber = String – type Phonebook = [(Name, Phonenumber)] ● can also contain parameters – type IntMap v = Map Int v
  • 26.
    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)