KEMBAR78
08. haskell Functions | PDF
Functions

         Sebastian Rettig


Every function in haskell consumes exactly
 Every function in haskell consumes exactly
    one parameter and returns aa value.
     one parameter and returns value.
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
Nice to remember (1)
    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'])
Nice to remember (2)
  Typeclass-Membership:
1. derive from existing Memberships of used types
  data Vector2D = Vector Float Float deriving (Show, Eq)

2. implement Membership by your own
  instance Show Vector2D where
    show Vector a b = “x: ” ++ [a] ++ “ ; y: ” ++ [b]
Curried Functions (1)
●   let's look at the Function header again, e.g:
    max :: (Ord a) => a -> a -> a
        1. we have a Typeclass restriction for Ord
        2. we have 2 Parameters of Types, who have a
            membership for the Ord Typeclass
        3. we have a return value of the same type
●   But, why is the syntax not separating the parameters
      better from the result set?
Curried Functions (2)
●   every function in haskell consumes exactly one
      parameter and returns a value
●   so we could write the function header instead of:
    max :: (Ord a) => a -> a -> a
●   also in the following way:
    max :: (Ord a) => a -> (a -> a)
        –   max is a function which consumes a parameter and
              returns a function
        –   these function consumes a parameter and returns a
              value (the max of both values)
●
    → Partial Application
Curried Functions (3)
●   some examples:
       –   :t max returns
                  max :: (Ord a) => a -> a -> a
       –   max 4 5 returns 5
       –   (max 4) 5 returns 5
       –   :t max 4 returns
                 max 4 :: (Num a, Ord a) => a -> a
       –   let foo = max 4
                  foo 5 returns 5
       –   :t max 4 5 returns
                  max 4 5 :: (Num a, Ord a) => a
Curried Functions (4)
●   we can also partial apply infix functions
    (/10) 2   returns    0.2
    (10/) 2   returns    5
    (++ “bar”) “foo”           returns “foobar”
    (“bar” ++) “foo”           returns “barfoo”
    :t (`elem` ['a'..'z'])
      (`elem` ['a'..'z']) :: Char -> Bool
    :t ('a' `elem`)
      (`elem` ['a'..'z']) :: [Char] -> Bool
    :t elem
      elem :: Eq a => a -> [a] -> Bool
Pointless Style
●   let's say, we have the following function:
    maxWithFour :: (Num a, Ord a) => a -> a
    maxWithFour x = max 4 x
●   what is the result of max 4 again?
    :t max 4 returns max 4 :: (Num a, Ord a) => a -> a
●   max 4 returns already a function which consumes a
      parameter, so we can simplify our function:
    maxWithFour :: (Num a, Ord a) => a -> a
    maxWithFour = max 4
●   but how can we achieve that with the following function?
    fn x = ceiling (negate (tan (cos (max 50 x))))
Function Application (1)
●   used with ($)
●   has the following header:
    :t ($)
      ($) :: (a -> b) -> a -> b
●   compared with SPACE (normal function application)
        –   ($) has lowest priority
        –   ($) is right associative   f $ g $ a b   = (f (g (a b)))
        –   SPACE has highest priority
        –   SPACE is left associative     f a b c    = (((f a) b) c)
Function Application (2)
●   what can we do with ($) ?
●   helps us to avoid parentheses:
        –   instead of:
              sum (map sqrt [1..20])
        –   we can write:
              sum $ map sqrt [1..20]
●   allows us also to wrap a value in a function:
    map ($ 3) [(4+), (10*), (^2), sqrt]
      returns
       [7.0,30.0,9.0,1.7320508075688772]
Function Composition (1)
●   Definition:
●   used with (.)
●   has the following header:
    :t (.)
      (.) :: (b -> c) -> (a -> b) -> a -> c
●   composing two functions produces a new function
●   good for on-the-fly pass of a function to the next
      function
Function Composition (2)
●   what can we do with (.) ?
●   helps us also to avoid parentheses
●   → unwraps the parameter out of parentheses
        –   instead of:
            map (xs -> negate (sum (tail xs))) [[1..5],
              [3..6],[1..7]]
        –   we can write:
            map (negate . sum . tail) [[1..5],[3..6],
              [1..7]]
Composition vs. Application (1)
●   IMPORTANT to know the difference between ($) and (.)
●   best to compare both headers again:
        –   ($) :: (a -> b) -> a -> b
        –   (.) :: (b -> c) -> (a -> b) -> a -> c
●   combination of both allows us parenthesis-less writing
●   shorter code and mostly easier to read
●   → possibility to write pointless-style functions with more
     then one function call
Composition vs. Application (2)
●   example with parameter:
        –   foo xs = sum (filter (> 10) (map (*2) xs))
        –   foo xs = sum $ filter (> 10) $ map (*2 ) xs
●   example without parameter (pointless-style):
        –   foo xs = sum (filter (> 10) (map (*2) xs))
        –   foo = sum . filter (> 10) . map (*2)
Useful Types
●   Maybe:
    data Maybe a = Nothing | Just a
        –     contains maybe a type a or Nothing
        –     good for handling e.g. Hashmap lookup
                   ●   Nothing if key not exist, else Value of type a
●   Either:
    data Either a b = Left a | Right b
      deriving (Eq, Ord, Read, Show)
        –     can contain type a or type b
        –     Left for e.g. Error Messages, Right for value
        –     like an extended Maybe with information for Nothing
Functor Typeclass (1)
    class Functor f where
      fmap :: (a -> b) -> f a -> f b
●   for things that can be mapped over
●   !!! Functor needs Types with 1 Typeparameter !!!
●   fmap gets a function and a type and maps the function over
      the type variable
●   Instance for List:
         –   Remember: List has 1 Typeparameter [a], but is just
               Syntactic Sugar for ([] a)
    instance Functor [] where
      fmap = map
         –   Example: fmap (*2) [2,3,4] returns [4,6,8]
Functor Typeclass (2)
    class Functor f where
      fmap :: (a -> b) -> f a -> f b
●   Instance for Maybe
    instance Functor Maybe where
      fmap g (Just x) = Just (g x)
      fmap g Nothing = Nothing
●   Example:
        –   fmap (+3) Nothing returns Nothing
        –   fmap (+3) (Just 4) returns (Just 7)
Functor Typeclass (3)
    class Functor f where
      fmap :: (a -> b) -> f a -> f b
●   Instance for Either
    instance Functor (Either a) where
      fmap f (Right x) = Right (f x)
      fmap f (Left x) = Left x
●   Either is a type with 2 Typeparameters!
●   → we have to permanently include the first parameter in the
      instance (curried function, partial application)
●   → fmap do not change the 1st Typeparameter, only the 2nd
●   → Left Type-Constructor of Either is often used for Error
      Messages
Functor Typeclass (4)
    class Functor f where
      fmap :: (a -> b) -> f a -> f b
●   Example:
         –   fmap (+3) (Left 4) returns (Left 4)
         –   fmap (+3) (Right 4) returns (Right 7)
●   what happens, if we try to do that?
      fmap (+) (Just 4)
●   let's look at the type:
                        :t fmap (+) (Just 4)
      fmap (+) (Just 4) :: Num a => Maybe (a -> a)
●   partial application, BUT we can not use the Functor instance
      on the result!
●   → we need an extension → Applicative Functors
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)

08. haskell Functions

  • 1.
    Functions Sebastian Rettig Every function in haskell consumes exactly Every function in haskell consumes exactly one parameter and returns aa value. one parameter and returns value.
  • 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.
    Nice to remember(1) 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'])
  • 5.
    Nice to remember(2) Typeclass-Membership: 1. derive from existing Memberships of used types data Vector2D = Vector Float Float deriving (Show, Eq) 2. implement Membership by your own instance Show Vector2D where show Vector a b = “x: ” ++ [a] ++ “ ; y: ” ++ [b]
  • 6.
    Curried Functions (1) ● let's look at the Function header again, e.g: max :: (Ord a) => a -> a -> a 1. we have a Typeclass restriction for Ord 2. we have 2 Parameters of Types, who have a membership for the Ord Typeclass 3. we have a return value of the same type ● But, why is the syntax not separating the parameters better from the result set?
  • 7.
    Curried Functions (2) ● every function in haskell consumes exactly one parameter and returns a value ● so we could write the function header instead of: max :: (Ord a) => a -> a -> a ● also in the following way: max :: (Ord a) => a -> (a -> a) – max is a function which consumes a parameter and returns a function – these function consumes a parameter and returns a value (the max of both values) ● → Partial Application
  • 8.
    Curried Functions (3) ● some examples: – :t max returns max :: (Ord a) => a -> a -> a – max 4 5 returns 5 – (max 4) 5 returns 5 – :t max 4 returns max 4 :: (Num a, Ord a) => a -> a – let foo = max 4 foo 5 returns 5 – :t max 4 5 returns max 4 5 :: (Num a, Ord a) => a
  • 9.
    Curried Functions (4) ● we can also partial apply infix functions (/10) 2 returns 0.2 (10/) 2 returns 5 (++ “bar”) “foo” returns “foobar” (“bar” ++) “foo” returns “barfoo” :t (`elem` ['a'..'z']) (`elem` ['a'..'z']) :: Char -> Bool :t ('a' `elem`) (`elem` ['a'..'z']) :: [Char] -> Bool :t elem elem :: Eq a => a -> [a] -> Bool
  • 10.
    Pointless Style ● let's say, we have the following function: maxWithFour :: (Num a, Ord a) => a -> a maxWithFour x = max 4 x ● what is the result of max 4 again? :t max 4 returns max 4 :: (Num a, Ord a) => a -> a ● max 4 returns already a function which consumes a parameter, so we can simplify our function: maxWithFour :: (Num a, Ord a) => a -> a maxWithFour = max 4 ● but how can we achieve that with the following function? fn x = ceiling (negate (tan (cos (max 50 x))))
  • 11.
    Function Application (1) ● used with ($) ● has the following header: :t ($) ($) :: (a -> b) -> a -> b ● compared with SPACE (normal function application) – ($) has lowest priority – ($) is right associative f $ g $ a b = (f (g (a b))) – SPACE has highest priority – SPACE is left associative f a b c = (((f a) b) c)
  • 12.
    Function Application (2) ● what can we do with ($) ? ● helps us to avoid parentheses: – instead of: sum (map sqrt [1..20]) – we can write: sum $ map sqrt [1..20] ● allows us also to wrap a value in a function: map ($ 3) [(4+), (10*), (^2), sqrt] returns [7.0,30.0,9.0,1.7320508075688772]
  • 13.
    Function Composition (1) ● Definition: ● used with (.) ● has the following header: :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c ● composing two functions produces a new function ● good for on-the-fly pass of a function to the next function
  • 14.
    Function Composition (2) ● what can we do with (.) ? ● helps us also to avoid parentheses ● → unwraps the parameter out of parentheses – instead of: map (xs -> negate (sum (tail xs))) [[1..5], [3..6],[1..7]] – we can write: map (negate . sum . tail) [[1..5],[3..6], [1..7]]
  • 15.
    Composition vs. Application(1) ● IMPORTANT to know the difference between ($) and (.) ● best to compare both headers again: – ($) :: (a -> b) -> a -> b – (.) :: (b -> c) -> (a -> b) -> a -> c ● combination of both allows us parenthesis-less writing ● shorter code and mostly easier to read ● → possibility to write pointless-style functions with more then one function call
  • 16.
    Composition vs. Application(2) ● example with parameter: – foo xs = sum (filter (> 10) (map (*2) xs)) – foo xs = sum $ filter (> 10) $ map (*2 ) xs ● example without parameter (pointless-style): – foo xs = sum (filter (> 10) (map (*2) xs)) – foo = sum . filter (> 10) . map (*2)
  • 17.
    Useful Types ● Maybe: data Maybe a = Nothing | Just a – contains maybe a type a or Nothing – good for handling e.g. Hashmap lookup ● Nothing if key not exist, else Value of type a ● Either: data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show) – can contain type a or type b – Left for e.g. Error Messages, Right for value – like an extended Maybe with information for Nothing
  • 18.
    Functor Typeclass (1) class Functor f where fmap :: (a -> b) -> f a -> f b ● for things that can be mapped over ● !!! Functor needs Types with 1 Typeparameter !!! ● fmap gets a function and a type and maps the function over the type variable ● Instance for List: – Remember: List has 1 Typeparameter [a], but is just Syntactic Sugar for ([] a) instance Functor [] where fmap = map – Example: fmap (*2) [2,3,4] returns [4,6,8]
  • 19.
    Functor Typeclass (2) class Functor f where fmap :: (a -> b) -> f a -> f b ● Instance for Maybe instance Functor Maybe where fmap g (Just x) = Just (g x) fmap g Nothing = Nothing ● Example: – fmap (+3) Nothing returns Nothing – fmap (+3) (Just 4) returns (Just 7)
  • 20.
    Functor Typeclass (3) class Functor f where fmap :: (a -> b) -> f a -> f b ● Instance for Either instance Functor (Either a) where fmap f (Right x) = Right (f x) fmap f (Left x) = Left x ● Either is a type with 2 Typeparameters! ● → we have to permanently include the first parameter in the instance (curried function, partial application) ● → fmap do not change the 1st Typeparameter, only the 2nd ● → Left Type-Constructor of Either is often used for Error Messages
  • 21.
    Functor Typeclass (4) class Functor f where fmap :: (a -> b) -> f a -> f b ● Example: – fmap (+3) (Left 4) returns (Left 4) – fmap (+3) (Right 4) returns (Right 7) ● what happens, if we try to do that? fmap (+) (Just 4) ● let's look at the type: :t fmap (+) (Just 4) fmap (+) (Just 4) :: Num a => Maybe (a -> a) ● partial application, BUT we can not use the Functor instance on the result! ● → we need an extension → Applicative Functors
  • 22.
    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)