如何在 DAML 中的函数内断言条件?
How do I assert conditions inside a function in DAML?
我有以下代码:
template Iou
with
issuer : Party
owner : Party
amount : Decimal
currency : Text
where
signatory issuer
mergeIou : Iou -> Iou -> Iou
mergeIou a b =
-- assert $ a.issuer == b.issuer
-- assert $ a.owner == b.owner
-- assert $ a.currency == b.currency
a with amount = a.amount + b.amount
当我取消注释任何断言时,出现以下错误:
* Couldn't match expected type `Iou' with actual type `m0 ()'
* In the expression:
assert
$ (DA.Internal.Record.getField @"issuer" a)
...
我做错了什么?
这里的问题是assert
有一个不纯的效果,所以不能用在纯
功能类似于 mergeIou
。解决这个问题最简单的方法是改变
mergeIou 具有类型 Iou -> Iou -> Update Iou
并将函数放在
做块。
即
mergeIou : Iou -> Iou -> Update Iou
mergeIou a b = do
assert $ a.issuer == b.issuer
assert $ a.owner == b.owner
assert $ a.currency == b.currency
pure $ a with amount = a.amount + b.amount
如果你需要的功能是纯粹的,就不能使用assert
。最简单的
另一种方法是使用 Optional
在类型中明确显示失败:
mergeIou : Iou -> Iou -> Optional Iou
mergeIou a b = do
unless (a.issuer == b.issuer) None
unless (a.owner == b.owner) None
unless (a.currency == b.currency) None
pure $ a with amount = a.amount + b.amount
为了帮助调试,我建议您改用 Either
,这样您就可以
确定哪个断言失败:
mergeIou : Iou -> Iou -> Either Text Iou
mergeIou a b = do
unless (a.issuer == b.issuer) $ Left "IOU issuers did not match"
unless (a.owner == b.owner) $ Left "IOU owners did not match"
unless (a.currency == b.currency) $ Left "IOU currencies did not match"
pure $ a with amount = a.amount + b.amount
为了更全面地讨论这里到底发生了什么,我建议你
阅读我对 Trouble using the getTime 的扩展回答
函数
我在这里讨论纯度和封装分类帐的概念
DAML 中的交互。
如果您利用 DAML 的 ActionFail
类型 class:
,实际上有一种方法可以从@Recurse 的回答中一次定义所有三个版本的 mergeIou
mergeIou : ActionFail m => Iou -> Iou -> m Iou
mergeIou a b = do
unless (a.issuer == b.issuer) $ fail "IOU issuers did not match"
unless (a.owner == b.owner) $ fail "IOU owners did not match"
unless (a.currency == b.currency) $ fail "IOU currencies did not match"
pure $ a with amount = a.amount + b.amount
我有以下代码:
template Iou
with
issuer : Party
owner : Party
amount : Decimal
currency : Text
where
signatory issuer
mergeIou : Iou -> Iou -> Iou
mergeIou a b =
-- assert $ a.issuer == b.issuer
-- assert $ a.owner == b.owner
-- assert $ a.currency == b.currency
a with amount = a.amount + b.amount
当我取消注释任何断言时,出现以下错误:
* Couldn't match expected type `Iou' with actual type `m0 ()'
* In the expression:
assert
$ (DA.Internal.Record.getField @"issuer" a)
...
我做错了什么?
这里的问题是assert
有一个不纯的效果,所以不能用在纯
功能类似于 mergeIou
。解决这个问题最简单的方法是改变
mergeIou 具有类型 Iou -> Iou -> Update Iou
并将函数放在
做块。
即
mergeIou : Iou -> Iou -> Update Iou
mergeIou a b = do
assert $ a.issuer == b.issuer
assert $ a.owner == b.owner
assert $ a.currency == b.currency
pure $ a with amount = a.amount + b.amount
如果你需要的功能是纯粹的,就不能使用assert
。最简单的
另一种方法是使用 Optional
在类型中明确显示失败:
mergeIou : Iou -> Iou -> Optional Iou
mergeIou a b = do
unless (a.issuer == b.issuer) None
unless (a.owner == b.owner) None
unless (a.currency == b.currency) None
pure $ a with amount = a.amount + b.amount
为了帮助调试,我建议您改用 Either
,这样您就可以
确定哪个断言失败:
mergeIou : Iou -> Iou -> Either Text Iou
mergeIou a b = do
unless (a.issuer == b.issuer) $ Left "IOU issuers did not match"
unless (a.owner == b.owner) $ Left "IOU owners did not match"
unless (a.currency == b.currency) $ Left "IOU currencies did not match"
pure $ a with amount = a.amount + b.amount
为了更全面地讨论这里到底发生了什么,我建议你 阅读我对 Trouble using the getTime 的扩展回答 函数 我在这里讨论纯度和封装分类帐的概念 DAML 中的交互。
如果您利用 DAML 的 ActionFail
类型 class:
mergeIou
mergeIou : ActionFail m => Iou -> Iou -> m Iou
mergeIou a b = do
unless (a.issuer == b.issuer) $ fail "IOU issuers did not match"
unless (a.owner == b.owner) $ fail "IOU owners did not match"
unless (a.currency == b.currency) $ fail "IOU currencies did not match"
pure $ a with amount = a.amount + b.amount