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
Extend type paths to handle record types #168
Conversation
a443aea
to
62767a4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a complementary point, paths seem to be required whenever the checking of a field is delayed, in a value. Which includes functions, and all the (lazy) thunks (which, right now, are only found in records).
Right, we need paths each time a contract generates one or more subcontracts that are delayed, so that we can follow the history if said subcontracts or one of their children fail. |
62767a4
to
5e3f306
Compare
Required to address #157. Type paths are used as representations of a subtype (syntactically) of a larger type used for error reporting. This PR extends them to handle types containing record types.
what it does
Field(Ident)
variant to path type elementsgoField
operator, analoguous to existinggoDom
andgoCodom
, in order for the future record builtin contract to construct type paths withField
elementswhat it does not
Context
Checking an higher-order contract involves checking several subcontracts on simpler types: for example, fully applying a function with a contract
Num -> Str -> Bool
involves automatic checking ofNum
,Str
andBool
contracts. If one of the subcontract fails, we like to indicate both the original complete higher-order type, but also the particular faulty subcontract: to this end, a subpart of the original type is represented by a type path, which is a list ofCodomain
orDomain
elements leading to the subcontract of interest.But this phenomenon is not limited to higher-order contracts: indeed, checking a record type
{ a: Num, b: Str, c: Bool }
also involves subcontracts. This was just not a concern until now since contracts for record types are not implemented (#157).This PR extends path elements, which could only be
Codomain
orDomain
, with a new constructorField(Ident)
, indicating that the path to a subtype goes through a record type and takes the branch of the corresponding field. In general, contracts may mix records types and arrow types: for example, in the contractNum -> {a : Str -> Str, b: Num}
, if the bound term return a record with a function wrongly returning aBool
in the fielda
, the type path accompanying the error would be[Codomain, Field("a"), Codomain]
.Example
[Disclaimer: this example does not work as it is on this branch, since contracts for records are not yet implemented. It uses a WIP implementation for the sake of the demonstration]
Example of error reporting with a general path mixing records and arrows:
Error message
Some effort have been put into error messages involving higher contracts in #141, which uses the shape of the type path to tune messages accordingly. Since "entering" a record type does not change polarity (records are just glorified products, after all), the same heuristics are kept, but it just ignores
Field
elements, as can be seen in the example above.