Here is a question from a total beginner in Daml (and functional programming).
Why do I get a parse error on the following line?: (iouSplitCid, iouRestCid) <- exercise iouCid Iou_Split with splitAmount=amount
The wording of the error:
Couldn't match type ‘ContractId Iou’ with ‘Optional a2’ arising from a functional dependency between: constraint ‘HasExercise Iou Iou_Split (Optional a1, Optional a2)’ arising from a use of ‘exercise’ instance ‘HasExercise Iou Iou_Split (IouCid, IouCid)’ at <no location info> .
Related instructions/declarations:
amount: Decimal
skier: Party
(iouCid, iouData) ← fetchByKey @Iou skier
template Iou
with
owner : Party
...
signatory owner
key owner: Party
maintainer key
controller owner can
Iou_Split : (IouCid, IouCid)
with
splitAmount: Decimal
do
...
Judging from the error, it looks like it’s not a parse error but a type error instead. It looks like the choice Iou_Split returns a pair (IouCid, IouCid) but you are using it in a context where an Optional a for some type a is expected.
Can you share the full example? That might make it easier to suggest a solution.
template SkiCandidate
with
skier: Party
reduction: SkipassReductionType
where
signatory skier
key skier: Party
maintainer key
nonconsuming choice PrepareTransfer: ContractId Iou
with
amount: Decimal
currency: Text
controller skier
do
-- assumption: a single Iou is present for a given owner
(iouCid, iouData) <- fetchByKey @Iou skier
iouData.owner === skier
assertMsg "IOU with a different currency - payment impossible" (iouData.currency == currency)
assertMsg "Not enough IOU-balance to send the transfer" (iouData.amount >= amount)
(iouSplitCid, iouRestCid) <- exercise iouCid Iou_Split with splitAmount=amount
...
type IouCid = ContractId Iou
template Iou
with
owner : Party
currency : Text
amount : Decimal
observers : [Party]
where
ensure amount > 0.0
signatory owner
observer observers
key owner: Party
maintainer key
controller owner can
-- Split the IOU by dividing the amount.
Iou_Split : (IouCid, IouCid)
with
splitAmount: Decimal
do
let restAmount = amount - splitAmount
splitCid <- create this with amount = splitAmount
restCid <- create this with amount = restAmount
return (splitCid, restCid)
I can’t quite reproduce the error in your example. There is one issue in PrepareTransfer: You need to return the contract id on the last line of the choice. The following code compiles for me:
module Main where
import DA.Assert
data SkipassReductionType = SkipassReductionType
deriving (Eq, Show)
template SkiCandidate
with
skier: Party
reduction: SkipassReductionType
where
signatory skier
key skier: Party
maintainer key
nonconsuming choice PrepareTransfer: ContractId Iou
with
amount: Decimal
currency: Text
controller skier
do
-- assumption: a single Iou is present for a given owner
(iouCid, iouData) <- fetchByKey @Iou skier
iouData.owner === skier
assertMsg "IOU with a different currency - payment impossible" (iouData.currency == currency)
assertMsg "Not enough IOU-balance to send the transfer" (iouData.amount >= amount)
(iouSplitCid, iouRestCid) <- exercise iouCid Iou_Split with splitAmount=amount
pure iouSplitCid
type IouCid = ContractId Iou
template Iou
with
owner : Party
currency : Text
amount : Decimal
observers : [Party]
where
ensure amount > 0.0
signatory owner
observer observers
key owner: Party
maintainer key
controller owner can
-- Split the IOU by dividing the amount.
Iou_Split : (IouCid, IouCid)
with
splitAmount: Decimal
do
let restAmount = amount - splitAmount
splitCid <- create this with amount = splitAmount
restCid <- create this with amount = restAmount
return (splitCid, restCid)
Due to my lack of understanding on how the Daml parser works, I have not included lines that directly follow the one with the error.
One of these lines:
assert(isSome iouSplitCid)
And here’s where the problem comes from. (Now I’m after a long explanatory session regarding some theory related to the issue.) The assert statement assumes iouSplitCid to be of type Optional, and carries this assumption over to the previous instruction (exercise iouCid…) where it is not met, thus the complaining.
Removing the erroneous assertion gets rid of the initial error.
@cocreature I apologize for providing you with incomplete information.
Thank you very much for all your efforts!