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)