# Homework 8

## Type classes

This homework is written in literate Haskell; you can download the raw source to fill in yourself. You’re welcome to submit literate Haskell yourself, or to start fresh in a new file, literate or not.

Please submit homeworks via the DCI submission page.

``````module Hw08 where

import Control.Applicative
import Data.Char``````

This homework will be published in two parts. Both parts are due on 2015-11-15, but the second part won’t be published until 2015-11-09.

The first part consists of three problems, all on type classes.

Second part consists of two problems: one using the material from lecture on Wednesday, one a short answer question.

## Part 1

Problem 1: `Eq` and `Show` (5pts)

``````data ArithExp =
Num Int
| Plus ArithExp ArithExp
| Times ArithExp ArithExp
| Neg ArithExp``````

Write `Eq` and `Show` instances for `ArithExp`.

The `Eq` instance should compare for structural equality—`Plus (Num 5) (Num 3) == Plus (Num 5) (Num 3)` yield `True`, but `Plus (Num 5) (Num 3) == Plus (Num 3) (Num 5)` yields `False`.

The `Show` instance should print as few parentheses as possible. That is, `show (Plus (Num 5) (Plus (Num 6) (Num 36)))` should return `"5 + 6 + 36"`, not `"5 + (6 + 36)"`. Similarly, `show (Plus (Num 5) (Times (Num 6) (Num 36)))` should return `5 + 6 * 36`, because multiplication has a higher precedence than addition. But `show (Times (Num 5) (Plus (Num 6) (Num 36)))` should return `"5 * (6 + 36)"`“.

``instance Eq ArithExp where``
``  _ == _ = undefined``
``````instance Show ArithExp where
show = undefined``````

Problem 2: `Setlike` (10pts)

Here is a type class `Setlike`. A given type constructor `f`, of kind `* -> *`, is `Setlike` if we can implement the following methods for it. (Recall `Listlike` from lecture.)

``````class Setlike f where
emp :: f a

singleton :: a -> f a

union :: Ord a => f a -> f a -> f a
union = fold insert

insert :: Ord a => a -> f a -> f a
insert = union . singleton

delete :: Ord a => a -> f a -> f a
delete x s = fold (\y s' -> if x == y then s' else insert y s') emp s

isEmpty :: f a -> Bool
isEmpty = (==0) . size

size :: f a -> Int
size = fold (\_ count -> count + 1) 0

isIn :: Ord a => a -> f a -> Bool
isIn x s = maybe False (const True) \$ getElem x s

getElem :: Ord a => a -> f a -> Maybe a

fold :: (a -> b -> b) -> b -> f a -> b

toAscList :: f a -> [a] -- must return the list sorted ascending
toAscList = fold (:) []``````

In the rest of this problem, you’ll define some instances for `Setlike` and write some code using the `Setlike` interface. Please write the best code you can. `Setlike` has some default definitions, but sometimes you can write a function that’s more efficient than the default. Do it. Write good code.

Define an instance of `Setlike` for lists. Here’s an example that should work when you’re done—it should be the set {0,2,4,6,8}.

``````evensUpToTen :: [Int]
evensUpToTen = fold insert emp [0,2,4,6,8]``````

Here’s a type of binary trees. Define a `Setlike` for BSTs, using binary search algorithms. Write good code. I expect insertion, lookup, and deletion to all be O(log n).

``data BST a = Empty | Node (BST a) a (BST a)``

Write `Eq` and `Show` instances for BSTs. These might be easier to write using the functions below.

``````instance Ord a => Eq (BST a) where
s1 == s2 = undefined``````
``````instance Show a => Show (BST a) where
show = undefined``````

Write the following set functions. You’ll have to use the `Setlike` interface, since you won’t know which implementation you get.

`fromList` should convert a list to a set.

``````fromList :: (Setlike f, Ord a) => [a] -> f a
fromList = undefined``````

`difference` should compute the set difference: X - Y = { x in X | x not in Y }.

``````difference :: (Setlike f, Ord a) => f a -> f a -> f a
difference xs ys = undefined``````

`subset` should determine whether the first set is a subset of the other one. X ⊆ Y iff ∀ x. x ∈ X implies x ∈ Y.

``````subset :: (Setlike f, Ord a) => f a -> f a -> Bool
subset xs ys = undefined``````

Problem 3: maps from sets (10pts)

Finally, let’s use sets to define maps—a classic data structure approach.

We’ll define a special notion of key-value pairs, `KV k v`, with instances to force comparisons just on the key part.

``````newtype KV k v = KV { kv :: (k,v) }

instance Eq k => Eq (KV k v) where
(KV kv1) == (KV kv2) = fst kv1 == fst kv2

instance Ord k => Ord (KV k v) where
compare (KV kv1) (KV kv2) = compare (fst kv1) (fst kv2)

instance (Show k, Show v) => Show (KV k v) where
show (KV (k,v)) = show k ++ " |-> " ++ show v``````
``````type Map f k v = f (KV k v)
type ListMap k v = Map [] k v
type TreeMap k v = Map BST k v``````

Now define the following map functions that work with `Setlike`.

``````emptyMap :: Setlike f => Map f k v
emptyMap = undefined

lookup :: (Setlike f, Ord k) => k -> Map f k v -> Maybe v
lookup k m = undefined

extend :: (Setlike f, Ord k) => k -> v -> Map f k v -> Map f k v
extend k v m = undefined

remove :: (Setlike f, Ord k) => k -> Map f k v -> Map f k v
remove k m = undefined

toAssocList :: Setlike f => Map f k v -> [(k,v)]
toAssocList = undefined``````

You’ll have to think hard about what to do for `lookup` and `remove`… what should `v` be? Can you use lazy evaluation to your advantage?

## Part 2

Problem 4: parsing with `Applicative` (10pts)

Note that you’ll need to add `import Control.Applicative` to the top of the file to get the below to work. You’ll also need to rename the `empty` method of the `Setlike` class to `emp`. Sorry for the confusion. :(

We’ll use `Applicative` to do some parsing. Here are the definitions from lecture.

``````pair :: Applicative f => f a -> f b -> f (a,b)
pair = liftA2 (,)

first :: (a -> b) -> (a,c) -> (b,c)
first f (a,c) = (f a, c)

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

instance Functor Parser where
fmap f p = Parser \$ \s -> maybe Nothing (Just . first f) (parse p s)``````
``````instance Applicative Parser where
pure a = Parser \$ \s -> Just (a,s)
f <*> a = Parser \$ \s -> maybe Nothing (\(g,s') -> parse (fmap g a) s') \$ parse f s

instance Alternative Parser where
empty = Parser \$ const empty
l <|> r = Parser \$ \s -> parse l s <|> parse r s

ensure :: (a -> Bool) -> Parser a -> Parser a
ensure p parser = Parser \$ \s ->
case parse parser s of
Nothing -> Nothing
Just (a,s') -> if p a then Just (a,s') else Nothing

where f [] = Just (Nothing,[])
f (c:s) = Just (Just c,c:s)

eof :: Parser ()
eof = Parser \$ \s -> if null s then Just ((),[]) else Nothing

zeroOrMore, oneOrMore :: Parser a -> Parser [a]
oneOrMore p = (:) <\$> p <*> zeroOrMore p -- a/k/a some
zeroOrMore p = oneOrMore p <|> pure [] -- a/k/a many

satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where f [] = Nothing
f (x:xs) = if p x then Just (x,xs) else Nothing

spaces :: Parser ()
spaces = pure () <* zeroOrMore (satisfy isSpace)

char :: Char -> Parser Char
char c = spaces *> satisfy (==c)

str :: String -> Parser String
str s = spaces *> loop s
where loop [] = pure []
loop (c:cs) = (:) <\$> satisfy (==c) <*> loop cs

type Id = String

data Expr =
EVar Id
| ETrue
| EFalse
| EIf Expr Expr Expr
| ENum Int
| EIncr Expr
| EDecr Expr
| EIsZero Expr
| EApp Expr Expr
| ELam Id Expr
deriving (Show, Eq)``````

Write a parser for the Expr language from HW05.

``````expr :: Parser Expr
expr = undefined``````

One of the key issues will be discriminating identifiers from tokens. You’ll want to use `lookahead` to do that. Good luck!

Problem 5: your thoughts on parsing (5pts)

You’ve now seen three different styles of parser—manually, using a lexer/parser generator, and using combinators—and written two of them, at least.

What are the pros and cons of each style?

What do you prefer?

Are there times when you would use one kind of parser over another?