Deprecation of constructors keyword
Migrate your code to remove the obsolete
constructorskeyword
On November 20, 2018 the language standard changed
to remove the need for the constructors keyword and beginning the deprecation cycle for the
constructors keyword.  This section describes what changed and how to migrate your code.
Changes
Before this change users would generate constructors for a union type using the constructors
keyword, which converted a union type into a record of constructors:
let Example = < Left : Natural | Right : Bool >
let example = constructors Example
in  [ example.Left 1, example.Right True ]
After this change, you can now access union constructors as if they were fields of the
original union type instead of creating an intermediate record of constructors.  For
example, this is now valid:
let Example = < Left : Natural | Right : Bool >
in  [ Example.Left 1, Example.Right True ]
Phases
The constructors keyword is being phased out in three steps:
- Phase 1 - Allow accessing constructors as fields of the union types - The first phase is backwards compatible, adding support for accessing constructors directly from a union type without changing the behavior of the - constructorskey word.
- Phase 2 - - constructors x = x- The second phase slightly breaks backwards compatibility by changing the constructors keyword to behaves as if it were the identity function for both type-checking and normalization purposes. In other words, any Dhall expression of the form: - constructors x - … behaves exactly as if it were just: - x - For the common idiom of: - let SomeUnionType = … let someUnionType = constructors SomeUnionType in … someUnionType.SomeConstructor … - … this is not a breaking change because - someUnionTypebecomes a synonym for- SomeUnionTypeand you can access constructors directly off the original union type just as you did for the old- constructorsrecord.- This change also improves type-checking and normalization performance because the interpreter no longer needs to materialize the intermediate record of constructors. Now the interpreter only needs to type-check and normalize the constructors that you actually use. - However, this is still a breaking change because - constructors xis now a type instead of a term. For example, this means that you can no longer store the expression- constructors xinside of a record containing other terms:- -- This expression used to type-check before this change and -- no longer type-checks afterwards { foo = constructors MyUnionType , bar = 1 } - This change would also break any code that gave an explicit type annotation to a - constructorsexpression (unlikely, but possible).
- Phase 3 - Remove the - constructorskeyword- This change is strongly backwards-incompatible by removing support for the - constructorskeyword, breaking all code that still uses the keyword.
Migration
- Phase 1 - Manually migrate your code - During Phase 1 the - dhallinterpreter does not provide support for code migration since replacing- constructors xwith- xis not a safe transformation until Phase 2. If you wish to migrate your code you will need to do so manually.- The main benefit of migrating your code manually (before Phase 2) is to get early access to the performance improvement from eliminating the intermediate - constructorsrecords.
- Phase 2 - Automatically migrate your code - During Phase 2 you can automatically migrate your code using - dhall lint, which will automatically replace all occurrences of- constructors xwith- xnow that this is a behavior-preserving transformation.
- Phase 3 - Your code breaks if you haven’t migrated - During Phase 3 the deprecation cycle is complete and if you haven’t migrated then your code will fail to type-check with an “Unbound variable: constructors” error message.