# 5. Safe pattern matching¶

Suppose we have the following `List`

EADT:

```
data ConsF a l = ConsF a l deriving (Functor)
data NilF l = NilF deriving (Functor)
eadtPattern 'ConsF "Cons"
eadtPattern 'NilF "Nil"
type List a = EADT '[ConsF a, NilF]
-- pattern for a specific EADT: List a
pattern ConsList :: a -> List a -> List a
pattern ConsList a l = Cons a l
```

We can use pattern matching on `List`

constructors:

```
showEADTList :: Show a => List a -> String
showEADTList = \case
ConsList a l -> show a ++ " : " ++ showEADTList l
Nil -> "Nil"
_ -> undefined
> putStrLn (showEADTList intList)
10 : 20 : 30 : Nil
```

However the compiler cannot detect that the pattern matching is complete, hence we have the choice between a warning or adding a wildcard match as we have done above.

Another solution is to rely on multi-continuations. Then we can provide a
function per constructor as in a pattern-matching. For instance, with
multi-continuations we can transform an `EADT '[A,B,C]`

into a function whose
type is `(A -> r, B -> r, C -> r) -> r`

. Hence the compiler will ensure that
we provide the correct number of alternatives in the continuation tuple (the
first parameter).

## 5.1. Explicitly recursive example¶

Transforming an EADT into a multi-continuation is done with `eadtToCont`

.
Mapping the continuation tuple is done with `>::>`

.

```
import Haskus.Utils.ContFlow
showCont' l = eadtToCont l >::>
( \(ConsF a r) -> show a ++ " : " ++ showCont' r -- explicit recursion
, \NilF -> "Nil"
)
> showCont' intList
"10 : 20 : 30 : Nil"
```

## 5.2. Catamorphism example¶

Transforming a `VariantF`

into a multi-continuation is done with
`toCont`

. It can be useful with recursion schemes.

```
import Haskus.Utils.ContFlow
showCont l = toCont l >::>
( \(ConsF a r) -> show a ++ " : " ++ r -- no explicit recursion
, \NilF -> "Nil"
)
> cata showCont intList
"10 : 20 : 30 : Nil"
```

## 5.3. Transformation example¶

We can use this approach to transform EADT. For instance list mapping:

```
import Haskus.Utils.ContFlow
mapList f l = toCont l >::>
( \(ConsF a r) -> Cons (f a) r
, \NilF -> Nil
)
> eadtShow (cata (mapList (+5)) intList :: List Int)
"15 : 25 : 35 : Nil"
```

We can also transform an EADT into another EADT:

```
-- Some new Even and Odd constructors
data EvenF a l = EvenF a l deriving (Functor)
data OddF a l = OddF a l deriving (Functor)
eadtPattern 'EvenF "Even"
eadtPattern 'OddF "Odd"
instance (Show a) => MyShow' (EvenF a) where
myShow' (EvenF a l) = show a ++ " {even} : " ++ l
instance (Show a) => MyShow' (OddF a) where
myShow' (OddF a l) = show a ++ " {odd} : " ++ l
-- convert Cons constructor into Odd or Even constructor, depending on the
-- cell value
evenOdd l = toCont l >::>
( \(ConsF a r) -> if even a then Even a r
else Odd a r
, \NilF -> Nil
)
intList' :: List Int
intList' = Cons (3 :: Int) $ Cons (4 :: Int) $ Cons (5 :: Int) Nil
> eadtShow (cata evenOdd intList' :: EADT '[EvenF Int, OddF Int, NilF])
"3 {odd} : 4 {even} : 5 {odd} : Nil"
```

## 5.4. Splitting constructors¶

We can chose to handle only a subset of the constructors of an EADT by using
`splitVariantF`

.

For instance in the following example we only handle `EvenF Int`

and `OddF Int`

constructors. The other ones are considered as left-overs:

```
alg x = case splitVariantF @'[EvenF Int, OddF Int] x of
Right v -> toCont v >::>
( \(EvenF a l) -> "Even : " ++ l
, \(OddF a l) -> "Odd : " ++ l
)
Left leftovers -> "something else"
```

We can test this code with:

```
eo :: EADT '[EvenF Int, OddF Int, NilF]
eo = cata evenOdd intList'
eo2 :: EADT '[ConsF Int, EvenF Int, OddF Int, NilF]
eo2 = Even (10 :: Int) $ Odd (5 :: Int) $ Cons (7 :: Int) $ Odd (7 :: Int) Nil
> cata alg eo
"Odd : Even : Odd : something else"
> cata alg eo2
"Even : Odd : something else"
```

Note that the traversal ends when it encounters an unhandled constructor.

## 5.5. Unordered continuations (`>:%:>`

)¶

By using the `>:%:>`

operator instead of `>::>`

, we can provide
continuations in any order as long as an alternative for each constructor is
provided.

The types must be unambiguous as the EADT type can’t be used to infer the
continuation types (as is done with `>::>`

). Hence the type ascriptions in the
following example:

```
showCont'' l = eadtToCont l >:%:>
( \(NilF :: NilF (List Int)) -> "Nil"
, \(ConsF a r) -> show (a :: Int) ++ " : " ++ showCont'' r
)
> showCont'' intList
"10 : 20 : 30 : Nil"
```