Context Sebastian Rettig An applicative value can be seen as a value with an added context. - A fancy value. An applicative value can be seen as a value with an added context. - A fancy value.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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.
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
(>, =, a -> a -> a also in the following way: max :: (Ord
a) => a -> (a -> a)
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
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
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
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
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!
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
:: * -> *
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?
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 *
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?
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?
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]
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)
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
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
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
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
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
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 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."]
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 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
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)