Successfully reported this slideshow.
Upcoming SlideShare
×

337 views

Published on

• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

1. 1. Context Sebastian RettigAn applicative value can be seen as aa value with An applicative value can be seen as value with an added context. - - A fancy value. an added context. A fancy value.
2. 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. 3. Haskell Features● Pure Functional Programming Language● Lazy Evaluation● Pattern Matching and Guards● List Comprehension● Type Polymorphism
4. 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. 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. 6. Nice to remember (3) Curried Function:● every function in haskell consumes exactly one parameter and returns a value● PARTIAL APPLICATION● 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)
7. 7. Nice to remember (4) Pointless Style:● based on partial Application → simpler code maxWithFour x = max 4 x is the same as maxWithFour = max 4● use Function Application (\$) to avoid Parenthesis on function call with parameters sqrt \$ 3 + 4 + 9● use Function Composition (.) to avoid Parenthesis on chaining functions fn = ceiling . negate . tan . cos . max 50
8. 8. Type Refresher (1) create a Type:● data MyVector = Nirvana | Single Int | Tuple Int Int | Triple Int Int Int● MyVector is the Type● Nirvana, Single, Tuple, Triple are Type Constructors● Type Constructors are normal functions :t Single is Single :: Int -> MyVector● Type Constructors can have Parameters (values) Single, Tuple, Triple have 1, 2 and 3
9. 9. Type Refresher (2) create a Type with Record Syntax:● data MyVector2 = Nirvana2 | Single2 {x :: Int} | Tuple2 {x :: Int, y :: Int} | Triple2 {x :: Int, y :: Int, z :: Int}● Nirvana2, Single2, Tuple2, Triple2 are Type Constructors● x, y, z are selectors functions who lookup specific fields in the data type → like GET functions :t x is x :: MyVector2 -> Int● e.g.: foo = Single2 {x=4} x foo returns 4 :t foo returns foo :: MyVector2
10. 10. Type Refresher (3) to make the Type more generic:● data MyVector3 a = Nirvana3 | Single3 {x :: a} | Tuple3 {x :: a, y :: a} | Triple3 {x :: a, y :: a, z :: a}● a is type parameter and selector x has the following header :t x is x :: MyVector3 a -> a● if we want to use this type, we have to set the Type parameter OR let Haskell detect the Type parameter● e.g.: foo = Single3 {x=4} :t foo returns foo :: MyVector3 Integer● e.g.: foo = Nirvana3 :t foo returns foo :: MyVector3 a
11. 11. Type Refresher (4) a Type can have more than one Type parameter:● data MyVector4 a b c = Nirvana4 | Single4 {x :: a} | Tuple4 {x :: a, y :: b} | Triple4 {x :: a, y :: b, z :: c}● a, b, c are type parameter, selector x has header :t x is x :: MyVector4 a b c -> a● e.g.: foo = Single4 {x=4} :t foo returns foo :: MyVector4 Integer b c● e.g.: foo = Nirvana4 :t foo returns foo :: MyVector4 a b c● → Partial Application!
12. 12. Kind● explains the steps which are necessary to evaluate the data from that type● → evaluate = the type is fully applied● can be used to find how much parameters a type has● GHCi- Command :k● :k MyVector returns MyVector :: *● :k MyVector2 returns MyVector2 :: *● :k MyVector3 returns MyVector3 :: * -> *● :k MyVector4 returns MyVector4 :: * -> * -> * -> *● :k MyVector3 Int returns MyVector3 Int :: *● :k MyVector4 Int Int returns MyVector4 Int Int :: * -> *
13. 13. Useful Types● Maybe: data Maybe a = Nothing | Just a – for operations, which can fail – contains data of type a (Just a) or Nothing – good for handling e.g. Hashmap lookup● 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 – BUT why is Error Message the first parameter?
14. 14. Implement Membership (1)● Lets refresh again how to implement a Typeclass- Membership:● first the definition of Typeclass Eq: :i Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool -- Defined in GHC.Classes● What is a ? → a is used by (==) and (/=) as parameter● → needs to be a fully applied type (concrete type)● → :k must return *
15. 15. Implement Membership (2)● But how can we make MyVector3 a member of Eq ?● → we have to make MyVector3 fully applied type, e.g.: instance Eq (MyVector3 Int) where Nirvana3 == Nirvana3 = True Single3 {x=x1} == Single3 {x=x2} = (x1 == x2) ...● Or with using generic Type Parameter: instance Eq (MyVector3 a) where Nirvana3 == Nirvana3 = True Single3 {x=x1} == Single3 {x=x2} = (x1 == x2) ...● do a has Type-Class restrictions? If yes, which?
16. 16. Implement Membership (3)● And what about that? instance Eq MyVector3 where Nirvana3 == Nirvana = True Single3 {x=x1} == Single {x=x2} = (x1 == x2) ...● Is this membership correct?
17. 17. 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 kind * -> * !!!● fmap gets a function and a type and maps the function over the type variable → the type variable can change!● Instance for List: instance Functor [] where fmap = map – Example: fmap (*2) [2,3,4] returns [4,6,8]
18. 18. 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) – fmap (show) (Just 4) returns (Just “4”)
19. 19. 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 kind * -> * -> * !● → we have to permanently include the first parameter in the instance (partial application)● → fmap only maps over the second Type-Parameter!● → Left Type-Constructor is often used for Error Messages
20. 20. 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)● lets 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 Just (4+)● → we need an extension → Applicative Functors
21. 21. Lifting a Function● if we partial apply fmap, the header has the following structure :t fmap (*2) results in fmap (*2) :: (Num a, Functor f) => f a -> f a :t fmap (cycle 3) results in fmap (cycle 3) :: (Functor f) => f a -> f [a]● → this is called lifting a function● → we can predefine a normal function which gets a Functor and returns a Functor● → we move the function inside the Type and operate on type variables● → we lift the function up to the type → normal function can work with complex types
22. 22. Applicative Functor (1) class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b● pure is a function who wraps a normal value into applicative – creates a minimal context● (<*>) takes a functor with a function in it and another functor – extracts that function from the first functor – and then maps it over the second one
23. 23. Applicative Functor (2) class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b● Instance for Maybe instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just f) <*> something = fmap f something● Example: – Just (+3) <*> Just 9 returns Just 12 – pure (+3) <*> Just 10 returns Just 13 – Just (++"hah") <*> Nothing returns Nothing
24. 24. Applicative Functor (3) class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b● Instance for [] instance Applicative [] where pure x = [x] fs <*> xs = [f x | f <- fs, x <- xs]● Example: – [(*0),(+100),(^2)] <*> [1,2,3] returns [0,0,0,101,102,103,1,4,9] – pure "Hey" :: [String] returns ["Hey"] – [(+),(*)] <*> [1,2] <*> [3,4] returns [4,5,5,6,3,4,6,8]
25. 25. Applicative Functor (4)● pure f <*> x equals fmap f x● → in Control.Applicative exists a specific function (<\$>) :: (Functor f) => (a -> b) -> f a -> f b f <\$> x = fmap f x● So we can do the same much prettier: (++) <\$> Just "johntra" <*> Just "volta" returns Just "johntravolta" (++) <\$> ["ha","heh","hmm"] <*> ["?","!","."] returns ["ha?", "ha!", "ha.", "heh?", "heh!", "heh.", "hmm?", "hmm!", "hmm."]
26. 26. Applicative Functor (5) class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b● Instance for IO instance Applicative IO where pure = return a <*> b = do f <- a x <- b return (f x)
27. 27. Applicative Functor (6) Example for IO:● instead of writing this: myAction :: IO String myAction = do a <- getLine b <- getLine return \$ a ++ b● we can write this: myAction :: IO String myAction = (++) <\$> getLine <*> getLine
28. 28. Applicative Context● Applicative Types can bee seen as Types with context: – Maybe, Either for things which can fail – [ ] as non-deterministic result – IO as values send or get from outside● Applicative functors allows us to operate in applicative types like normal types and provide the context!● → We dont need to pattern match against the Context in every operation we use in our functions!
29. 29. Lifting a Function (Applicative)● Function lifting in for Applicative: liftA :: Applicative f => (a -> b) -> f a -> f b – same as fmap – fmap :: Functor f => (a -> b) -> f a -> f b liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c liftA2 f a b = f <\$> a <*> b – gets a function, with 2 parameters – operates on 2 Applicatives – result is also an Applicative