unison/unison-src/transcripts/pattern-match-coverage.md

283 lines
4.3 KiB
Markdown
Raw Normal View History

2022-09-29 23:33:23 +03:00
```ucm:hide
.> builtins.merge
```
# Basics
## non-exhaustive patterns
2022-09-29 23:33:23 +03:00
```unison:error
unique type T = A | B | C
test : T -> ()
test = cases
2023-02-28 00:12:10 +03:00
A -> ()
2022-09-29 23:33:23 +03:00
```
```unison:error
unique type T = A | B
test : (T, Optional T) -> ()
test = cases
(A, Some _) -> ()
(A, None) -> ()
(B, Some A) -> ()
(B, None) -> ()
```
## redundant patterns
2022-09-29 23:33:23 +03:00
```unison:error
unique type T = A | B | C
test : T -> ()
test = cases
2023-02-28 00:12:10 +03:00
A -> ()
B -> ()
C -> ()
_ -> ()
2022-09-29 23:33:23 +03:00
```
```unison:error
unique type T = A | B
test : (T, Optional T) -> ()
test = cases
(A, Some _) -> ()
(A, None) -> ()
(B, Some _) -> ()
(B, None) -> ()
(A, Some A) -> ()
```
# Uninhabited patterns
match is complete without covering uninhabited patterns
2022-09-29 23:33:23 +03:00
```unison
unique type V =
test : Optional (Optional V) -> ()
test = cases
None -> ()
Some None -> ()
```
uninhabited patterns are reported as redundant
2022-09-29 23:33:23 +03:00
```unison:error
unique type V =
2023-03-08 20:24:21 +03:00
test0 : V -> ()
test0 = cases
_ -> ()
```
```unison:error
unique type V =
2022-09-29 23:33:23 +03:00
test : Optional (Optional V) -> ()
test = cases
None -> ()
Some None -> ()
Some _ -> ()
```
# Guards
## Incomplete patterns due to guards should be reported
2022-09-29 23:33:23 +03:00
```unison:error
test : () -> ()
test = cases
() | false -> ()
```
```unison:error
test : Optional Nat -> Nat
test = cases
None -> 0
Some x
| isEven x -> x
```
## Complete patterns with guards should be accepted
```unison:error
test : Optional Nat -> Nat
test = cases
None -> 0
Some x
| isEven x -> x
| otherwise -> 0
```
# Pattern instantiation depth
Uncovered patterns are only instantiated as deeply as necessary to
distinguish them from existing patterns.
2022-09-29 23:33:23 +03:00
```unison:error
unique type T = A | B | C
test : Optional (Optional T) -> ()
test = cases
None -> ()
Some None -> ()
```
```unison:error
unique type T = A | B | C
test : Optional (Optional T) -> ()
test = cases
None -> ()
Some None -> ()
Some (Some A) -> ()
```
# Literals
## Non-exhaustive
Nat
2022-09-29 23:33:23 +03:00
```unison:error
test : Nat -> ()
test = cases
0 -> ()
```
Boolean
```unison:error
test : Boolean -> ()
test = cases
true -> ()
```
## Exhaustive
Nat
2022-09-29 23:33:23 +03:00
```unison
test : Nat -> ()
test = cases
0 -> ()
_ -> ()
```
Boolean
```unison
2022-09-29 23:33:23 +03:00
test : Boolean -> ()
test = cases
true -> ()
false -> ()
2022-09-29 23:33:23 +03:00
```
# Redundant
Nat
```unison:error
test : Nat -> ()
2022-09-29 23:33:23 +03:00
test = cases
0 -> ()
0 -> ()
_ -> ()
2022-09-29 23:33:23 +03:00
```
Boolean
2022-09-29 23:33:23 +03:00
```unison:error
test : Boolean -> ()
test = cases
true -> ()
false -> ()
_ -> ()
```
# Sequences
## Exhaustive
2022-09-29 23:33:23 +03:00
```unison
test : [()] -> ()
test = cases
[] -> ()
x +: xs -> ()
```
## Non-exhaustive
2022-09-29 23:33:23 +03:00
```unison:error
test : [()] -> ()
test = cases
[] -> ()
```
```unison:error
test : [()] -> ()
test = cases
x +: xs -> ()
```
```unison:error
test : [()] -> ()
test = cases
xs :+ x -> ()
```
```unison:error
test : [()] -> ()
test = cases
x0 +: (x1 +: xs) -> ()
[] -> ()
```
```unison:error
test : [()] -> ()
test = cases
[] -> ()
x0 +: [] -> ()
```
## Uninhabited
`Cons` is not expected since `V` is uninhabited
```unison
unique type V =
test : [V] -> ()
test = cases
[] -> ()
```
## Length restrictions can equate cons and nil patterns
Here the first pattern matches lists of length two or greater, the
second pattern matches lists of length 0. The third case matches when the
final element is `false`, while the fourth pattern matches when the
first element is `true`. However, the only possible list length at
the third or fourth clause is 1, so the first and final element must
be equal. Thus, the pattern match is exhaustive.
2022-09-29 23:33:23 +03:00
```unison
test : [Boolean] -> ()
test = cases
[a, b] ++ xs -> ()
[] -> ()
xs :+ false -> ()
true +: xs -> ()
```
This is the same idea as above but shows that fourth match is redundant.
2022-09-29 23:33:23 +03:00
```unison:error
test : [Boolean] -> ()
test = cases
[a, b] ++ xs -> ()
[] -> ()
xs :+ true -> ()
true +: xs -> ()
_ -> ()
```
This is another similar example. The first pattern matches lists of
length 5 or greater. The second matches lists of length 4 or greater where the
first and third element are true. The third matches lists of length 4
or greater where the final 4 elements are `true, false, true, false`.
The list must be exactly of length 4 to arrive at the second or third
clause, so the third pattern is redundant.
2022-09-29 23:33:23 +03:00
```unison:error
test : [Boolean] -> ()
test = cases
[a, b, c, d, f] ++ xs -> ()
[true, _, true, _] ++ _ -> ()
_ ++ [true, false, true, false] -> ()
_ -> ()
```