2021-01-08 15:50:15 +03:00
# Daml template syntax desugaring
2019-04-04 11:33:38 +03:00
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
2021-01-08 15:50:15 +03:00
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.
2019-04-04 11:33:38 +03:00
2021-01-08 15:50:15 +03:00
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.
2019-04-04 11:33:38 +03:00
2021-01-08 15:50:15 +03:00
## How Daml syntax desugars
2019-04-04 11:33:38 +03:00
### 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
```
2021-01-08 15:50:15 +03:00
The `class Template` (defined by the Daml standard library) represents the set of all contract types:
2019-04-04 11:33:38 +03:00
```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
```
2021-01-08 15:50:15 +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
2021-01-08 15:50:15 +03:00
The next contract exercises the "contract keys" feature of Daml.
2019-07-31 02:49:33 +03:00
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
```