# Notes (TLPH 10/15): First Class Families

# 10.1 Defunctionalization

## Exercise 10.1-i

The fact that `Fst a b`

is parameterized on both `a`

and `b`

confused me for a moment. On this problem I wasn’t sure what `ListMaybe`

should be parameterized on. Then I realized that what defunctionalization basically is taking a type signature with an explicit `forall`

and rewriting it:

```
fst :: forall a b. (a, b) -> a
listMaybe :: forall a. [a] -> Maybe a
```

The transformation is a little like this:

```
fst :: forall a b. (a, b) -> a
Fst a b = Fst (a, b)
```

And the return type goes into the functional dependency in the `Eval`

class.

The really trippy thing is that we actually gain a degree of freedom here by duplicating `Fst`

as both a type and data constructor. Consider the pathological case:

```
data Fst' a b = Snd' (a, b)
data Snd' a b = Fst' (a, b)
instance Eval (Fst' a b) a where
Snd' (a, b)) = a
eval (
instance Eval (Snd' a b) b where
Fst' (a, b)) = b eval (
```

And when we evaluate:

```
*FirstClass> eval (Fst' ("hello", True))
True
*FirstClass> eval (Snd' ("hello", True))
"hello"
```

## 10.2 Type-Level Defunctionalization

Oh cool! My observation from the previous chapter is answered here when we move to the type-level, because type constructors automatically promote to kind constructors, i.e. `Exp a`

(which is just a wrapped `->`

) is both a type and a kind from a single declaration.

I think the `_1`

in `type instance Eval (FromMaybe _1 ('Just a)) = a`

is a wildcard? It still compiles replacing `_1`

with `_`

. Standby…

Okay, having experimented, it’s a *labeled* wildcard:

`type instance Eval (FromMaybe _1 ('Just a)) = _1`

Which works as expected:

```
*FirstClass> :kind! Eval (FromMaybe "nothing" ('Just "just"))
Eval (FromMaybe "nothing" ('Just "just")) :: GHC.Types.Symbol
= "nothing"
```

## Exercise 10.2-i

see `FirstClass.hs`

## Exercise 10.2-ii

see `FirstClass.hs`

```
*FirstClass> :kind! Eval (Foldr Cons '[] '[1, 2, 3, 4])
Eval (Foldr Cons '[] '[1, 2, 3, 4]) :: [GHC.Types.Nat]
= '[1, 2, 3, 4]
```

## 10.4 Ad-Hoc Polymorphism

## Exercise 10.4-i

`type instance Eval (Map f '(a, b)) = '(a, Eval (f b))`