You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/manual/generalized-algebraic-data-types.mdx
+18-9Lines changed: 18 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,8 @@ type timezone =
33
33
34
34
Using this variant type, we will end up having functions like this:
35
35
36
-
```res example
36
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
37
+
```res
37
38
let convertToDaylight = tz => {
38
39
switch tz {
39
40
| EST => EDT
@@ -47,15 +48,17 @@ This function is only valid for a subset of our variant type's constructors but
47
48
48
49
Let's see if we can find a way for the compiler to help us with normal variants. We could define another variant type to distinguish the two kinds of timezone.
49
50
50
-
```res example
51
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
52
+
```res
51
53
type daylightOrStandard =
52
54
| Daylight(timezone)
53
55
| Standard(timezone)
54
56
```
55
57
56
58
This has a lot of problems. For one, it's cumbersome and redundant. We would now have to pattern-match twice whenever we deal with a timezone that's wrapped up here. The compiler will force us to check whether we are dealing with daylight or standard time, but notice that there's nothing stopping us from providing invalid timezones to these constructors:
57
59
58
-
```res example
60
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
61
+
```res
59
62
let invalidTz1 = Daylight(EST)
60
63
let invalidTz2 = Standard(EDT)
61
64
```
@@ -78,7 +81,8 @@ type rec timezone<_> =
78
81
We define our type with a type parameter. We manually annotate each constructor, providing it with the correct type parameter indicating whether it is standard or daylight. Each constructor is a `timezone`,
79
82
but we've added another level of specificity using a type parameter. Constructors are now understood to be `standard` or `daylight` at the _type_ level. Now we can fix our function like this:
80
83
81
-
```res example
84
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
85
+
```res
82
86
let convertToDaylight = tz => {
83
87
switch tz {
84
88
| EST => EDT
@@ -92,7 +96,8 @@ The compiler can infer correctly that this function should only take `timezone<s
92
96
we try to return a standard timezone from this function. Actually, this seems like it could be a problem,
93
97
we still want to be able to match on all cases of the variant sometimes, and a naive attempt at this will not pass the type checker. A naive example will fail:
94
98
95
-
```res example
99
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
100
+
```res
96
101
let convertToDaylight = tz =>
97
102
switch tz {
98
103
| EST => EDT
@@ -104,7 +109,8 @@ let convertToDaylight = tz =>
104
109
105
110
This will complain that `daylight` and `standard` are incompatible. To fix this, we need to explicitly annotate to tell the compiler to accept both:
106
111
107
-
```res example
112
+
{/* TODO: fix this example, it has an error because it doesn't have access to the previous snippet */}
113
+
```res
108
114
let convertToDaylight : type a. timezone<a> => timezone<daylight> = // ...
109
115
```
110
116
@@ -117,7 +123,8 @@ Sometimes, a function should have a different return type based on what you give
117
123
118
124
[^1]: In ReScript v12, the built-in operators are already generic, but we use them in this example for simplicity.
119
125
120
-
```res example
126
+
{/* this example purposefully has an error so it is not marked as an example */}
127
+
```res
121
128
type rec number<_> = Int(int): number<int> | Float(float): number<float>
122
129
123
130
let add = (type a, x: number<a>, y: number<a>): a =>
@@ -204,7 +211,8 @@ This API has a method for binding event handlers, `on`. This takes an event and
204
211
depending on which event we are binding to. A naive implementation might look similar to this, defining a
205
212
separate method for each stream event to wrap the unsafe version of `on`.
206
213
207
-
```res example
214
+
{/* TODO: fix this example, it has an error */}
215
+
```res
208
216
module Stream = {
209
217
type t
210
218
@@ -233,7 +241,8 @@ The real magic happens in the signature of `on`. Read it carefully, and then loo
233
241
follow how the type variables are getting filled in, write it out on paper what each type variable is equal
0 commit comments