docs: add page about opaque types - #1246
jderochervlk wants to merge 1 commit into
Conversation
5498056 to
2773cdd
Compare
Cloudflare deploymentDeployement ID: f8a06913-13b5-4e68-a148-cf516fbfd334 ⛅️ wrangler 4.63.0 (update available 4.81.1) ✨ Uploading _redirects |
|
I'm not sure we want to call them "opaque", "distinct", or "branded" types. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2773cdd6da
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| Let's start with out email example using an imaginary `EmailApi` that sends a message to an email address we provide it. | ||
|
|
||
| ```res |
There was a problem hiding this comment.
Add validation markers to the new code blocks
Every code fence on this page is plain res, so scripts/test-examples.mjs skips the entire page because it only parses res example, res prelude, and res sig blocks. As a result, the invalid calls on lines 16, 22, and 65 pass yarn test; mark the intended-valid snippets with the supported fence types and provide any required prelude so documentation examples remain compiler-checked.
AGENTS.md reference: AGENTS.md:L195-L195
Useful? React with 👍 / 👎.
| We would get failures is we tried to send a message to an invalid email address. | ||
|
|
||
| ```res | ||
| sendEmail("not_an_email**123") |
There was a problem hiding this comment.
Supply the message in the invalid-email call
This call cannot demonstrate a runtime failure for an invalid address because the preceding sendEmail function takes two unlabelled arguments, while this invocation supplies only one. ReScript 12 rejects it for incorrect arity before EmailAPI.send can run, so pass a message argument here.
Useful? React with 👍 / 👎.
| let sendEmail: (t, string) => unit | ||
| } = { | ||
| type t = string | ||
| let sendEmail = (email: t, message: t) => EmailAPI.send((email :> string), string) |
There was a problem hiding this comment.
Pass the message value instead of the string type
The refactored implementation passes string as the second argument, but that is a type name rather than a value; ReScript reports that the value string cannot be found. It also unnecessarily annotates message as the email type t; use message: string and pass message to EmailAPI.send, and make the equivalent value correction in the earlier example on line 16.
Useful? React with 👍 / 👎.
| --- | ||
|
|
||
| The `:>` operator may be used to convert a polymorphic variant to a `string` or `int`, or convert an [object](../docs/manual/object.mdx) to a type with a subset of its fields. | ||
| The `:>` operator may be used to convert a polymorphic variant to a `string` or `int`, to downcast an [opaque type](../docs/manual/opaque-types.mdx) to it's primitive type, or convert an [object](../docs/manual/object.mdx) to a type with a subset of its fields. |
There was a problem hiding this comment.
Limit opaque coercion to private manifest types
This new description is false for the page's primary type t form: outside a module that exports an abstract type t, ReScript 12 rejects (value :> string) because the representation is unknown. The coercion is available when the interface exposes type t = private string; distinguish that private manifest form instead of promising that any opaque type can be downcast.
AGENTS.md reference: AGENTS.md:L59-L59
Useful? React with 👍 / 👎.
| } | ||
| ``` | ||
|
|
||
| `:>` is the type coercion operator It cannot be used to change a type to a different primitive value, such as `(42 :> string)`, but we can use it to allow our opaque type to be passed to functions that work on the primitive type that it's based on. Once this is done, the value is now longer the opaque type and it will become the type we coerced it to.n We can always use an opaque type as a primitive type, but we cannot use a primitive type as an opaque type. |
There was a problem hiding this comment.
Repair the garbled coercion explanation
The central explanation says the coerced expression is “now longer” opaque and ends the next clause with the stray text to.n, which reverses and obscures the intended statement. Change this to “no longer the opaque type” and remove the stray character so readers can understand what type the coerced expression has.
Useful? React with 👍 / 👎.
Fixes #543 and #508