Как мне установить условия внутри функции в DAML? - PullRequest
1 голос
/ 12 марта 2019

У меня есть следующий код:

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)
...

Что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 19 марта 2019

Существует способ определить все три версии mergeIou из ответа @ Recurse за один раз, если вы используете класс типов ActionFail DAML:

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
1 голос
/ 14 марта 2019

Проблема здесь в том, что assert имеет нечистый эффект, поэтому его нельзя использовать в чистой функции, такой как mergeIou.Самый простой способ решить эту проблему - изменить mergeIou на тип Iou -> Iou -> Update Iou и поместить функцию в do-блок.

т.е..

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

Для более полного обсуждения того, что именно здесь происходит, я предлагаю вам прочитать мой расширенный ответ на Проблема с использованием функции getTime , где я обсуждаю понятия чистоты и инкапсуляции регистра.взаимодействия в DAML.

...