Accessing an optional return value in DAML script
I have an Asset template created based on the DA ex-collateral repo here. An asset has Merge and Split operations. What I’m attempting to do is, within the scope of one ‘do’ block in DAML script, to split and asset and merge the two parts back. However, I have not been able to find the right syntax to access the returned objects from Split correctly.
I believe the reason is the definition of the split action returning an ‘Optional’, which I’m not sure how to access.
The asset template’s Split function:
template Asset
...
controller owner can
Split
: (ContractId Asset, Optional (ContractId Asset))
with splitQuantity: Int
do
splitCid <- create this with quantity = splitQuantity
restCid <-
if quantity == splitQuantity
then return None
else do
cid <- create this with quantity = quantity - splitQuantity
return (Some cid)
return (splitCid, restCid)
As you can see, it returns a tuple where the second item is Optional.
In DAML script, I have the following working block which runs fine:
do
...
splitResult <- submit partyX do
exerciseCmd existingAssetObject Split
with
splitQuantity = 50
My attempt at code to merge them back:
mergedBack <- submit partyX do
exerciseCmd splitResult._1 Merge
with
otherCid = splitResult._2
splitResult._1 seems accessible. However, splitResult._2 does not work and gives the following error:
• Couldn't match type ‘Optional (ContractId Asset)’
with ‘ContractId Asset’
arising from a functional dependency between:
constraint ‘DA.Internal.Record.HasField
"_2"
(ContractId Asset, Optional (ContractId Asset))
(ContractId Asset)’
What is the simplest way to access the optional return value?
Hi antvi and welcome to the forum!
The optional type is described in Module DA.Optional — Daml SDK 2.2.0 documentation.
In your case, there are two options:
-
if you are sure that the option will not be a
None(becausesplitQuantitywill be different thanquantityin your use-case) then I suggest usingfromSometo extract the value from the option (orfromSomeNotefor a nicer error message) -
if, on the other hand, you want to consider the case where the option corresponds to a
None, you could do as follows:
mergedBack <- case splitResult._2 of
Some cid -> submit partyX do
exerciseCmd cid Merge
with
otherCid = splitResult._1
None -> pure splitResult._1
In the latter case, you are effectively returning splitResult._1 unchanged if there is no asset to merge.
Thanks a lot for your reply Matteo! ![]()
I was able to use fromSome directly, but ran into an issue with your better example. After a couple tries, I reversed which split parts were used for the logic, and got the following to work:
mergedBack <- case splitResult._2 of
Some cid -> submit partyX do
exerciseCmd splitResult._1 Merge -- using the guaranteed-to-exist split part here
with
otherCid = cid -- using the optional-to-exist split part here
None -> pure splitResult._1
Glad you got it to work!
There was indeed a typo in my code code snippet above.
Cheers,
Matteo