Проблема с использованием функции getTime - PullRequest
0 голосов
/ 20 февраля 2019

Я использую getTime в операторе assert для выбора контракта следующим образом:

Add_Car : CarId
        with
            startCoverage: Time
        do
          -- Check for a legal start date
          assert (
            startCoverage > getTime
            )
          create this with datetime_vehicle_added = startCoverage, covered=True

Он генерирует ошибку:

error:
    * Couldn't match expected type `Time' with actual type `m0 Time'
    * In the second argument of `(>)', namely `getTime'
      In the first argument of `assert', namely
        `(startCoverage > getTime)'
      In a stmt of a 'do' block: assert (startCoverage > getTime)

Не возвращает ли getTime значение типа 'Время'?что такое мо время?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

tldr: Для @bame вам необходимо связать результат getTime в Update или Scenario do-block.т.е.

Add_Car : CarId
  with
    startCoverage: Time
  do
  -- Check for a legal start date
  now <- getTime
  assert $ startCoverage > now
  create this with datetime_vehicle_added = startCoverage, covered=True

Чтобы понять, что здесь произошло, нам нужно начать с типа getTime:

getTime : (HasTime m) => m Time

Сигнатура типа ожидаемой функции - одна из:

getTimeValue : Time

getTimeFunc : () -> Time

Чтобы понять разницу, вам нужно рассмотреть понятия чистоты и инкапсуляции.

Чистота

В DAML все функции чистые.

Чистая функция - это функция, которая может быть полностью описана в терминах отображения значений, передаваемых в качестве аргументов, значениям, возвращаемым в результате.Значения - это конкретные вещи, такие как Time, Int, Text и т. Д., Списки, записи и варианты значений, а также некоторые другие вещи, о которых я расскажу позже.getTimeValue - это значение, поэтому оно по определению является константой, которая будет только «текущим временем» в смысле «остановленных часов».

getTimeFunc - это функция, которая принимает аргумент типаUnit, что означает, что есть только один аргумент, который вы можете передать ему: ().Поскольку функция является чистой, это означает, что она не может рассматривать что-либо вне своего аргумента, поэтому эта функция также должна возвращать постоянное значение.На самом деле единственная разница между getTimeValue и getTimeFunc заключается в том, что вы должны передать getTimeFunc (), чтобы получить константу.

Инкапсуляция

То, что существует внешний мир сПонятие «текущего времени», которое вы можете опрашивать и использовать, - это «Контекст», который означает, что любая функция, которая использует это, более не может быть описана полностью в терминах ввода -> вывода.Это описывается как «нечистый».

В DAML все функции чистые, поэтому, если мы хотим обработать «нечистоту», мы должны заключить примесь в чистое значение.В DAML мы выражаем эту инкапсуляцию в виде типа:

encapsulatedImpureValue : m a

, поэтому в нашем случае значение равно Time:

encapsulatedImpureTimeValue : m Time

Вы можете прочитать это как,инкапсулированное значение типа Time, которое зависит от контекста m для оценки.Поскольку мы ничего не упомянули о контексте m, кроме того, что он существует, этого недостаточно для его реализации.В частности, мы должны также сказать, что контекст должен быть единым с понятием «текущее время», и именно так мы получаем сигнатуру getTime в стандартной библиотеке DAML:

getTime : (HasTime m) => m Time

Что вы можете прочитать как: инкапсулированное значение времени Time, которое зависит от контекста m, которое поддерживает HasTime (т. Е. Понятие «текущего времени»).

Использование инкапсулированных значений

Теперь мы можем написать:

let now = getTime

и now будет чистым инкапсулированным значением - что не сразу полезно, так как любая попытка использовать его влюбая функция, ожидающая чистого значения Time, потерпит неудачу, так как это потребует нарушения инкапсуляции, и DAML строго предписывает нарушения инкапсуляции как ошибки компиляции.

Чтобы использовать инкапсулированное значение, вы должны сначала указать подходящий контекст, изатем запустите значение в этом контексте.DAML предоставляет два контекста, которые поддерживают HasTime: Update и Scenario.Он также предоставляет один способ запуска Scenario упакованных значений и один способ запуска Update упакованных значений, а также два способа преобразования Update значений в Scenario значений.

  1. Каждое значение сценария верхнего уровня в модуле DAML будет выполняться интерпретатором DAML как тест DAML.

  2. Тело каждого варианта шаблона DAML определено как значение Updateкоторый будет запущен при выполнении выбора.

  3. Вы можете использовать функции submit и submitMustFail для получения значения Scenario, которое при запуске будет запускатьUpdate значение, разрешенное как назначенное Party.

Составление инкапсулированных значений

Существует ряд стандартных API, общих для почти всех функциональных языков для составленияинкапсулированные значения в составные значения.Вы услышите о самых известных: "Функтор" и "Монад"Определите функции, которые принимают инкапсулированные значения и функции и комбинируют их различными способами.Инкапсуляция является настолько фундаментальным принципом разработки программного обеспечения, что неудивительно, что большинство языков FP предоставляют синтаксический сахар для упрощения их использования - и DAML ничем не отличается.

Инкапсулированное значение, которое является экземпляром FunctorИнтерфейс поддерживает функцию fmap, для которой DAML также предоставляет в качестве инфиксного оператора <$>.

Инкапсулированное значение, являющееся экземпляром интерфейса Monad (называемое Action в DAML), поддерживает fmap, pure и функции bind / flatMap.DAML предоставляет return в качестве псевдонима для pure;и оператор >>= для bind / flatMap.Он также предоставляет do-нотацию как синтаксический сахар для >>=, поэтому:

do
  t <- getTime
  a <- useTime t
  combineWithTime a t

Создает составное значение Update, которое (при запуске) запускает getTime, передает полученное значение в useTime затем передает оба результата combineWithTime.Результатом этого do-блока также является инкапсулированное значение Update, поэтому мы не нарушаем инкапсуляцию, потому что к моменту запуска updateA/B/C мы предоставили контекст инкапсуляции для включающего составного Update значения.

Если (как вы делаете в своем примере) мы сделаем так, чтобы do заблокировал тело выбора, то при выполнении выбора будет запущено составное обновление.В качестве альтернативы, если мы передадим его в submit, мы можем запустить его как часть сценария.Если вы не сделаете ни одного (что может случиться, если, например, у вас есть два значения Update и вы используете выражение if для выбора между ними), это не окажет заметного эффекта, потому что в DAML все функции чистые.

0 голосов
/ 20 февраля 2019

getTime имеет смысл только как часть транзакции, где существует концепция времени бухгалтерской книги.m0 - это переменная типа, которая ссылается на Update или Scenario, в зависимости от вашего контекста.На практике это просто означает, что вам нужно привязать результат getTime к переменной внутри вашего блока do:

do
  currentTime <- getTime
  assert ( startCoverage > currentTime )
...