Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant of std.contract.from_predicate to specify an error message #1957

Closed
yannham opened this issue Jun 13, 2024 · 0 comments · Fixed by #1970
Closed

Variant of std.contract.from_predicate to specify an error message #1957

yannham opened this issue Jun 13, 2024 · 0 comments · Fixed by #1970
Assignees

Comments

@yannham
Copy link
Member

yannham commented Jun 13, 2024

Is your feature request related to a problem? Please describe.

It's a bit verbose and unintuitive to write a custom contract as a partial identity, passing a label around and returning the original value in case of success. For simple (and eager) contracts, sometimes we just want to return "accept" or "reject". This is in essence the role of std.contract.from_predicate, which takes a boolean function and make a contract out of it.

However, one limitation is precise error reporting: because predicates can only return true or false, they can't distinguish between different error cases with dedicated error messages. While predicates work well for simple contracts, where the user can just tell from the contract's name and the reported faulty value what went wrong, it doesn't scale to more complex cases. In those cases, the user is back to writing fun label value => ....

The addition of enum variants open a new possibility in the middle: we can specify a contract as an eager, boolean-like predicate, but with additional data attached, such as e.g. an error message, notes, etc. I suspect the vast majority of contracts, that are currently written as general partial identities, are actually simple predicates that could be written using those "extended" predicates, which are simpler to write and more intuitive.

Another benefit of having user writing contracts this way instead of general function, beyond being more intuitive for users, is that given #1466 and the ongoing work on boolean combinators, more contracts would be amenable to boolean operations like or (because those extended predicates can trivially be converted to predicates). This is not the case of the same contract written as a partial identity.

Describe the solution you'd like

While I'm not set on the exact data that can be returned, I think the most natural approach is to simply pass anything that can go into a label: a message, notes, etc. Using default values or optional, we can make it easily backward compatible if we ever add more stuff to labels (at the cost of not being a purely static type anymore). So, I would like to add a function to std.contract:

bikeshedme_from_validator : [| 'Ok, 'Error { message | String, notes | Array String | default = [] } |] -> __Contract
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant