102 lines
2.0 KiB
Markdown
102 lines
2.0 KiB
Markdown
# Functor
|
|
|
|
Parsing an expression in parenthesis:
|
|
|
|
```haskell
|
|
parseP :: Parser AST
|
|
parseP = do symbol '('
|
|
t <- exp
|
|
symbol ')'
|
|
return t
|
|
```
|
|
|
|
Before we write this sort of code, we need to understand `type classes` (especially `monads`)
|
|
|
|
## Types vs Typeclasses
|
|
|
|
| Types | Type classes |
|
|
| ------ | ------------ |
|
|
| Bool | Eq |
|
|
| Char | Show |
|
|
| AST | Num |
|
|
| String | Functor |
|
|
| | Monad |
|
|
|
|
**Eq**: typeclass equality; A type can only be typeclass equality if two like types can be compared
|
|
|
|
A type can be a *member* (instance) of a type class, meaning that if has the properties/functions that the class requires
|
|
|
|
e.g. `Bool` is an instance of `Eq` and `Show`
|
|
|
|
###### Is there a type that is **not** in `Eq`?
|
|
|
|
```haskell
|
|
(\c -> c :: Int) == (\c -> c :: Int)
|
|
```
|
|
|
|
**ERROR**: No instance for `Eq(Int -> Int)`
|
|
|
|
Why?
|
|
|
|
```haskell
|
|
f :: Int -> Int
|
|
g :: Int -> Int
|
|
```
|
|
|
|
Then `f == g` should be `fn == gn` for every n, the computer cannot do this (halting problem).
|
|
|
|
## Type Constructors
|
|
|
|
A type constructor takes a type to construct a new type.
|
|
|
|
`Maybe` - not a type but a type constructor
|
|
|
|
`Maybe String` - a type
|
|
|
|
```haskell
|
|
newtype Parser a = P (String -> [a, String])
|
|
```
|
|
|
|
**Parser** is a type constructor
|
|
|
|
**Parser AST** is a type
|
|
|
|
Functor is a typeclass of which `parser` is an instance
|
|
|
|
##### Functor
|
|
|
|
```haskell
|
|
class Functor f where
|
|
fmap :: (a -> b) -> fa -> fb
|
|
|
|
instance Functor Maybe where
|
|
fmap g (Just x) = Just (g x)
|
|
fmap g Nothing = Nothing -- fmap id = id
|
|
|
|
-- lists
|
|
instance Functor [] where
|
|
fmap g [] = []
|
|
fmap g (t:ts) = (g t) : fmap g ts
|
|
|
|
-- goal: write parser as a functor
|
|
newtype Parser a = P ( String -> [a, String] )
|
|
-- Need: fmap :: (a->b) -> Parser a -> Parser b
|
|
|
|
instance Functor Parser where
|
|
fmap g pa = -- parser pa
|
|
P (\str -> map (\(x,s) -> (gx,s))
|
|
parse pa str)
|
|
```
|
|
|
|
##### Rules of Functors
|
|
|
|
```haskell
|
|
fmap id = id -- identity
|
|
fmap (f . g) = fmap f . fmap g
|
|
```
|
|
|
|
Haskell doesn't enforce these rules however it is convention.
|
|
|
|
|
|
|