Chapters from 9th to 11th in CIS 194 formed nice bundle of related lectures, so I tackled them as a group.

Functor is really just a type class used to define a type that can be mapped over. Just like an a list can be mapped over with *map*, functors can be too. Name of the function used in that case is *fmap*. Functor is defined as:

class Functor f where
fmap :: (a -> b) -> f a -> f b
(<>) :: a -> f b -> f a

Things one can fmap over include things like *Maybe*, *List* and *Either* among other things. For example, we can apply (map over) function on Maybe Integer, without having to check if the value is Just or Nothing:

> fmap (+1) $ Just 1
Just 2
> fmap (+1) Nothing
Nothing

Applicative takes this idea one step further:

class Functor f => Applicative (f :: * -> *) where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a

That’s a mouthful, but by keeping our heads cool, parseable and very useful. The idea is that with applicative, you can place a function in special context and apply values that are also in similar context to it. For example

> pure (+) <*> Just 2 <*> Just 4
Just 6
> pure (+) <*> Nothing <*> Just 4
Nothing
> (++) <$> Just "Hello " <*> Just "World"
Just "Hello World"

Different applicatives behave differently. *Maybe* act as a computation that might fail, while *List* is computation with uncertain answer:

> (+) <$> [1, 2] <*> [4, 5]
[5,6,6,7]

Exercise in applicatives was about building parsers. The idea was to use *Parser* defined as:

newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }

and build small parsers that could then be combined to bigger parsers. One could even have simple logic like *a or b* while choosing which parser to apply next. For example, to define a parser that takes a string of two integers and pairs them up into a tupple, one could use following:

intPair :: Parser String
intPair = pairUp <$> posInt <* space <*> posInt
where pairUp a b = show a ++ " " ++ show b
space = satisfy (== ' ')

and in action. Notice how unparsed text is also returned. This allows chaining of parsers together. First one parser eats string a little bit a returns result and rest of the string, then next parser does the same thing and process continues:

> runParser intPair "23 34 56 foo"
Just ("23 34"," 56 foo")

### Like this:

Like Loading...

*Related*