Skip to content

Commit 0bfb9dd

Browse files
committed
Add an example in Plinth; extend Plinth section to discuss unboxed modules
1 parent 2331f6f commit 0bfb9dd

File tree

1 file changed

+68
-5
lines changed

1 file changed

+68
-5
lines changed

CIP-plutus-modules/README.md

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,16 +519,15 @@ scripts representing modules; the latter are subject to an additional
519519
syntactic restriction that the script body must be a tuple. We change
520520
the `Script` type accordingly
521521
```
522-
data Script = CompleteValidatorScript CompiledCode
523-
| ValidatorScript CompiledCode [ScriptArg]
524-
| CompleteModuleScript CompiledCode
525-
| ModuleScript CompiledCode [ScriptArg]
522+
data Script = ValidatorScript CompiledCode [ScriptArg]
523+
| ModuleScript CompiledCode [ScriptArg]
526524
```
527525
so that the deserializer can easily check the new syntactic
528526
restriction. `Script`s used as `ScriptArg`s may only be of the
529527
`ModuleScript` form (this requires a dynamic check). The idea is that
530528
a module provides a number of exports, which are the components of the
531-
tuple.
529+
tuple. (Again, special cases for an empty list of script arguments
530+
can be included in this type if desired).
532531

533532
In addition, expressions `M` referring to modules (of the form `proj j
534533
Mods`) may only appear in contexts of the form `proj i M`, projecting
@@ -636,6 +635,20 @@ these.
636635
It is `Module` values that would then be serialised to produce scripts
637636
for inclusion in transactions.
638637

638+
In the 'unboxed modules' variation we need to distinguish two kinds of
639+
scripts, scripts which define modules, and scripts which define
640+
validators. In Plinth, this distinction can be made in the types, by
641+
turning the `Module` type into a GADT with an extra parameter, of type
642+
```
643+
data ScriptType = ModuleScript | ValidatorScript
644+
```
645+
`applyModule` would be given a more restrictive type:
646+
```
647+
applyModule :: Module s (a->b) -> Module ModuleScript a -> Module s b
648+
```
649+
thus ensuring that only scripts representing modules are passed as
650+
script arguments.
651+
639652
### Plutus Ledger Language Versions
640653

641654
Plutus ledger language version is what "Plutus V1", "Plutus V2", "Plutus V3" refer to.
@@ -1356,6 +1369,56 @@ algorithms, because their code is smaller, and easier to fit within
13561369
the script size limit. Removing the need to make such choices can
13571370
potentially improve performance considerably.
13581371

1372+
### Example: Defining and using a Set module
1373+
1374+
As an example of how the module system might be used in a high-level
1375+
language, consider the following code, which defines and uses a module
1376+
implementing set insertion and membership testing, using an ordered
1377+
binary tree.
1378+
```
1379+
data Tree a = Leaf | Branch (Tree a) a (Tree a)
1380+
1381+
empTree = Leaf
1382+
1383+
insTree a Leaf = Branch Leaf a Leaf
1384+
insTree a (Branch l b r)
1385+
| a < b = Branch (insTree a l) b r
1386+
| a > b = Branch l b (insTree a r)
1387+
| a== b = Branch l b r
1388+
1389+
memTree a Leaf = False
1390+
memTree a (Branch l b r)
1391+
| a < b = memTree a l
1392+
| a > b = memTree a r
1393+
| a== b = True
1394+
1395+
data Set = Set {emptySet :: forall a. Tree a,
1396+
insertSet :: forall a. Ord a => a -> Tree a -> Tree a,
1397+
memberSet :: forall a. Ord a => a -> Tree a -> Bool}
1398+
1399+
setMod = Set empTree insTree memTree
1400+
1401+
setModule :: Module Set
1402+
setModule = makeModule ($$(PlutusTx.compile [| setMod |]))
1403+
1404+
client set redeemer _ = memberSet set redeemer s
1405+
where s = insertSet set 1 (insertSet set 2 (emptySet set))
1406+
1407+
clientModule = makeModule ($$(PlutusTx.compile [| client |]))
1408+
`applyModule` setModule
1409+
```
1410+
Here the module signature is represented by a Haskell record type;
1411+
Haskell records are compiled into tuples in UPLC, and the record
1412+
fields are all values (once fixpoints are floated upwards to the
1413+
module level), so the `setModule` in this example fits the 'unboxed
1414+
modules' syntactic restrictions. The client script takes the record as
1415+
an argument, and uses the module exports via record field selectors,
1416+
which compile to projections from the tuple. Thus the client also
1417+
meets the syntactic restrictions for 'unboxed modules'. To make use
1418+
of these modules, the off-chain code must construct a UTxO
1419+
containing `setModule` as a reference script, and include it as a
1420+
reference UTxO in transactions that use the client.
1421+
13591422
### Related work
13601423

13611424
#### Merkelized Validators

0 commit comments

Comments
 (0)