-
Notifications
You must be signed in to change notification settings - Fork 205
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
Proposal: Fixing generic templates over the Ledger API #3504
Comments
I can't think of anything better so it gets my thumbs up. As for the open questions:
|
I fully support the plan. I agree with @bame-da on 1 in that we should keep non-generic templates as they are now. There should be an easy path into using DAML where things that are only required for using advanced features impact you negatively. Regarding 2, let's do what we just agreed on the whiteboard. |
For the codegen our plan is:
Given the assumption in the codegen that there is only one instance in a DAR, should we enforce in DAML-LF that there is only one instance per package (i.e. per DALF)? We already have package-wide checks for name collisions so this shouldn’t be “less” modular than we already are. |
@hurryabit @cocreature do we still need
The only thing that varies between template instances are the choices (though in practice even that is unlikely). The choices are now defined on a static class names like the template instance so two template instances no longer collide. |
That’s a good point but on the other hand we have also gone away from your proposal of resolving from |
True, but I've come around that that's unavoidable. The developer overhead of having to write |
Great, I completely agree with that so sounds like we’re all on the same page now 👍 |
Closing since we decided to postpone generic templates for now, see #3606 |
Current Status
If you define a generic template in DAML, we currently create a record with the corresponding type parameters and the name of the generic templates. Once you create an instance of that generic template, we will create a new record in DAML-LF with the type parameters specialized to the ones in the instance and with the name of the instance. In DAML-LF those two records are unrelated and only the monomorphized record is a template. In DAML, the monomorphized record does not exist. We only create a type synoynym for the specialized version of the generic record.
The functions for interacting with the generic template take care of monomorphizing things as necessary, e.g.,
create
in DAML generates a DAM-LF function that takes the generic record, converts it to the monomorphic record and then calls the DAML-LF create primitive. Similarly forexercise
and other methods.However, this falls apart once you interact with a generic template via the Ledger API. E.g., if you a choice returning a value of type
type FooA = Foo A
in DAML, the DAML-LF return type will beFoo A
. However, that type is not a template, so if you try to pass the result of the choice to acreate
it will complain about a mismatch (if you omit the record id, you get lucky but imho that is more of an accident). It is even worse, if you have a choice accepting aContractId FooA
in DAML. The DAML-LF choice accepts aContractId (Foo A)
which passes the LF typechecker. However, if you try to exercise this choice, the engine will throw an error complaining thatFoo A
can’t possibly be a template since it has a type parameter so a contract id of that type doesn’t make sense.Effectively, this makes generic templates pretty much unusable over the Ledger API so we need to do something.
Proposed Changes
DAML-LF
ContractId (Foo X)
andContractId FooX
are valid over the ledger API.Foo X
toFooX
in general as there can be two templates for the same record type specialization in different modules and/or different packages.create
andexercise
will continue to require a template id instead of the record it.Open Questions
ContractId
type which providesexercise
. Given that the mapping fromFoo X
toFooX
is not unique, this is no longer possible. The codegen can only decode toContractId (Foo X)
and then the user has to make a choice which template they want to use which could either be done by something likeconstructor ContractId<FooX>(ContractId<Foo<X>>)
or a static method on theFooX
class with a signature likeexercise(ContractId<Foo<X>>, …)
.Affected Components
damlc
.cc @gerolf-da @remyhaemmerle-da @hurryabit @bame-da @tweber-da
The text was updated successfully, but these errors were encountered: