2019-04-04 11:33:38 +03:00
# DAML template syntax desugaring
2020-01-02 23:21:13 +03:00
Copyright 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All Rights Reserved.
2019-04-04 11:33:38 +03:00
SPDX-License-Identifier: (Apache-2.0 OR BSD-3-Clause)
## Introduction
DAML syntax describes contracts and the choices that operate on them. When DAML syntax is interpreted, the first step is to parse it to Haskell abstract syntax trees.
This note shows how DAML examples are desugared by showing their Haskell source equivalents, and should help you understand the connection between DAML and Haskell.
## How DAML syntax desugars
### Example (1)
Here is a contract with one choice:
```haskell
template Iou
with
issuer : Party
owner : Party
2019-11-29 18:13:15 +03:00
amount : Decimal
2019-04-04 11:33:38 +03:00
regulators : [Party]
where
2019-11-29 18:13:15 +03:00
ensure amount > 0.0
2019-04-13 17:04:30 +03:00
signatory issuer, owner
2019-04-04 11:33:38 +03:00
observer regulators
2019-11-29 18:13:15 +03:00
agreement show issuer < > " will pay " < > show owner < > " " < > show amount
2019-04-04 11:33:38 +03:00
choice Transfer : ContractId Iou
with
newOwner : Party
controller owner
do
create this with owner = newOwner
```
The `class Template` (defined by the DAML standard library) represents the set of all contract types:
```haskell
2019-07-31 02:49:33 +03:00
class Template t where
signatory : t -> [Party]
observer : t -> [Party]
ensure : t -> Bool
agreement : t -> Text
create : t -> Update (ContractId t)
fetch : ContractId t -> Update t
archive : ContractId t -> Update ()
2019-10-14 18:00:00 +03:00
toAnyTemplate : t -> AnyTemplate
fromAnyTemplate : AnyTemplate -> Optional t
2019-04-04 11:33:38 +03:00
```
2019-07-31 02:49:33 +03:00
In this example, `t` is identified with `Iou` . The rest of this section shows you how desugaring proceeds.
2019-04-04 11:33:38 +03:00
2019-07-31 02:49:33 +03:00
First we have data type definitions for the `Iou` template and the `Transfer` choice.
2019-04-04 11:33:38 +03:00
```haskell
2019-07-31 02:49:33 +03:00
data Iou = Iou with
2019-04-04 11:33:38 +03:00
issuer : Party
2019-07-31 02:49:33 +03:00
owner : Party
amount : Decimal
regulators : [Party]
deriving (Eq, Show)
2019-04-04 11:33:38 +03:00
2019-07-31 02:49:33 +03:00
data Transfer = Transfer with
newOwner : Party
deriving (Eq, Show)
2019-04-04 11:33:38 +03:00
```
2019-11-29 18:13:15 +03:00
Next we have the instance of the `Template` typeclass:
2019-04-04 11:33:38 +03:00
```haskell
2019-11-29 18:13:15 +03:00
instance Template Iou where
ensure this@Iou {..} = amount > 0.0
agreement this@Iou {..}
= show issuer < > " will pay " < > show owner < > " " < > show amount
signatory this@Iou {..}
= concat
[concat
[toParties (owner),
toParties (issuer)]]
observer this@Iou {..}
= concat
[concat
[concat
[toParties (regulators)]]]
archive cid
= exercise cid Archive
create = magic @"create"
fetch = magic @"fetch"
toAnyTemplate = magic @"toAnyTemplate"
fromAnyTemplate = magic @"fromAnyTemplate"
_templateTypeRep = magic @"_templateTypeRep"
2019-04-04 11:33:38 +03:00
```
2019-07-31 02:49:33 +03:00
When a type `t` is a `Template` instance, `class Choice` (defined by the DAML standard library) defines a (multi-parameter type class) relation on types `t` , `c` and `r` such that `r` is uniquely determined by the pair `(t, c)` :
2019-04-04 11:33:38 +03:00
```haskell
2019-07-31 02:49:33 +03:00
class Template t => Choice t c r | t c -> r where
exercise : ContractId t -> c -> Update r
2019-11-20 13:40:14 +03:00
_toAnyChoice : proxy t -> c -> Any
_fromAnyChoice : proxy t -> Any -> Optional c
2019-04-04 11:33:38 +03:00
```
2019-07-31 02:49:33 +03:00
In this example, `c` is identified with `Transfer` and `r` with `ContractId Iou` .
2019-04-04 11:33:38 +03:00
2019-07-31 02:49:33 +03:00
The `instance` declaration establishes the triple `(Iou, Transfer, ContractId Iou)` as satisfying the `Choice` relation:
2019-04-04 11:33:38 +03:00
```haskell
2019-07-31 02:49:33 +03:00
instance Choice Iou Transfer (ContractId Iou) where
2019-11-29 18:13:15 +03:00
exercise = magic @"exerciseIouTransfer"
_toAnyChoice = magic @"toAnyChoiceIouTransfer"
_fromAnyChoice
= magic @"fromAnyChoiceIouTransfer"
```
Information about a choice that is not part of the `Choice` typeclass is recorded in a
separate top-level identifier. Specifically, this is a tuple containing the controller,
the choice body and information on whether the choice is pre-, post- or nonconsuming:
```
_choice_IouTransfer :
(Iou -> Transfer -> [Party],
ContractId Iou
-> Iou -> Transfer -> Update (ContractId Iou),
PreConsuming Iou)
_choice_IouTransfer
= (\ this@Iou {..} arg@Transfer {..}
-> let
in
concat
2020-01-02 23:21:13 +03:00
[toParties (owner)],
2019-11-29 18:13:15 +03:00
\ self this@Iou {..} arg@Transfer {..}
-> let
2020-01-02 23:21:13 +03:00
in do create (DA.Internal.Record.setField @"owner" newOwner this),
2019-11-29 18:13:15 +03:00
PreConsuming)
2019-04-04 11:33:38 +03:00
```
2019-07-31 02:49:33 +03:00
### Example (2)
2019-04-04 11:33:38 +03:00
2019-07-31 02:49:33 +03:00
The next contract exercises the "contract keys" feature of DAML.
Contract key syntax desugars to `instance` declarations of the following typeclass.
2019-04-04 11:33:38 +03:00
```haskell
2019-07-31 02:49:33 +03:00
class Template t => TemplateKey t k | t -> k where
key : t -> k
fetchByKey : k -> Update (ContractId t, t)
lookupByKey : k -> Update (Optional (ContractId t))
2019-11-29 18:13:15 +03:00
_maintainer : proxy t -> k -> [Party]
2019-11-20 13:40:14 +03:00
_toAnyContractKey : proxy t -> k -> Any
_fromAnyContractKey : proxy t -> Any -> Optional ks
2019-04-04 11:33:38 +03:00
```
2019-04-13 17:04:30 +03:00
In the following `Enrollment` contract, there are no choices but there are declarations of `key` and `maintainer` .
2019-07-31 02:49:33 +03:00
2019-04-13 17:04:30 +03:00
```haskell
data Course =
Course with
institution : Party
title : Text
deriving (Show, Eq)
data Registration =
Registration with
student : Party
course : Course
year : Int
deriving (Show, Eq)
template Enrollment
with
reg : Registration
where
signatory reg.student, reg.course.institution
key reg : Registration
2019-06-05 17:27:38 +03:00
maintainer key.course.institution
2019-04-13 17:04:30 +03:00
```
2019-07-31 02:49:33 +03:00
The `Course` and `Registration` data types remain as they are, but the `Enrollment` template results in several pieces after desugaring.
2019-04-13 17:04:30 +03:00
```haskell
2019-07-31 02:49:33 +03:00
data Enrollment =
Enrollment with
reg : Registration
deriving (Show, Eq)
2019-04-13 17:04:30 +03:00
2019-11-29 18:13:15 +03:00
instance Template Enrollment where
signatory this@Enrollment {..}
= concat
[concat
[toParties
((DA.Internal.Record.getField
@"institution" (DA.Internal.Record.getField @"course" reg))),
toParties
((DA.Internal.Record.getField @"student" reg))]]
observer this@Enrollment {..} = concat []
ensure this@Enrollment {..} = True
agreement this@Enrollment {..} = ""
archive cid
= exercise cid Archive
create = magic @"create"
fetch = magic @"fetch"
toAnyTemplate = magic @"toAnyTemplate"
fromAnyTemplate = magic @"fromAnyTemplate"
_templateTypeRep = magic @"_templateTypeRep"
2019-04-13 17:04:30 +03:00
instance TemplateKey Enrollment Registration where
2019-11-29 18:13:15 +03:00
key this@Enrollment {..} = reg
_maintainer _ key
= concat
[concat
[toParties
((DA.Internal.Record.getField
@"institution" (DA.Internal.Record.getField @"course" key)))]]
fetchByKey = magic @"fetchByKey"
lookupByKey = magic @"lookupByKey"
_toAnyContractKey = magic @"_toAnyContractKey"
_fromAnyContractKey
= magic @"_fromAnyContractKey"
2019-07-31 02:49:33 +03:00
```