使用getTime函数时遇到问题

时间:2019-02-20 17:51:32

标签: monads daml

我在合同选择的assert语句中使用getTime,如下所示:

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是否不返回“ Time”类型的值?什么是“ mo时间”?

2 个答案:

答案 0 :(得分:2)

getTime仅在存在分类帐时间概念的事务中才有意义。 m0是一个类型变量,它根据您的上下文引用UpdateScenario。实际上,这仅意味着您需要将getTime的结果绑定到do块内的变量:

do
  currentTime <- getTime
  assert ( startCoverage > currentTime )

答案 1 :(得分:2)

tldr:,按@bame,您需要将getTime的结果绑定到Update中 或Scenario做封锁。即。

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中,所有功能都是纯函数。

纯函数是一个可以完全描述为 作为参数传递的值与作为参数返回的值之间的映射 结果。值是具体的东西,例如时间,整数,文本等,以及列表, 记录,值的变体以及我将要了解的其他一些内容 后来。 getTimeValue是一个值,因此根据定义它是一个常数, 只是“停止时钟”意义上的“当前时间”。

getTimeFunc是一个函数,其参数类型为Unit,其中 表示您可以传递一个参数:()。因为 函数是纯函数,这意味着它不能考虑其函数之外的任何事物 参数,因此此函数还必须返回一个常数。实际上 getTimeValuegetTimeFunc之间的唯一区别是您必须 传递getTimeFunc ()以获得常数。

封装

存在一个带有“当前时间”概念的外部世界, 可以讯问和使用的是“上下文”,这意味着使用 在输入->输出方面,这不再完全描述。 这被描述为“不纯”。

在DAML中,所有功能都是纯函数,因此,如果我们要处理“杂质”,我们有 将杂质封装成纯净值。在DAML中,我们表达了这一点 封装类型:

encapsulatedImpureValue : m a

所以在我们的例子中,值是Time值:

encapsulatedImpureTimeValue : m Time

您可以将其读取为Time类型的封装值,该值取决于 要评估的上下文m。由于我们还没有提及 上下文m除了存在之外,还不足以让我们 实施它。具体来说,我们还需要说上下文必须是 一个带有“当前时间”的概念,这就是我们最终得到的 DAML标准库中getTime的签名:

getTime : (HasTime m) => m Time

您可以这样理解:时间Time的封装值取决于 支持m的上下文HasTime(即“当前时间”的概念)。

使用封装的值

我们现在可以写:

let now = getTime

now将是纯封装的值-不会立即 很有用,因为任何在期望纯Time的函数中使用它的尝试 值将失败,因为这将需要破坏封装和DAML 严格将封装违规作为编译错误。

要使用封装的值,必须首先指定合适的上下文,并且 然后运行该上下文中的值。 DAML提供了两个上下文 支持HasTimeUpdateScenario。它还提供了一种运行方式 Scenario包装的值,以及运行Update包装的值的一种方法, 以及将Update值转换为Scenario值的两种方法。

  1. DAML模块中的每个顶级方案值将由DAML运行 解释程序作为DAML测试。

  2. 每个DAML模板选择的主体都定义为Update值 会在行使选择权时运行。

  3. 您可以使用submitsubmitMustFail函数生成一个 Scenario值,在运行时将运行一个授权为 提名的Update

组成封装值

几乎所有通用的标准API都有很多 用于将封装的值组成复合词的功能语言 价值观。您将听到最著名的:“ Functor”和“ Monad” 这些定义采用封装值和函数的函数,以及 以各种方式将它们结合起来。封装是这样的基础软件 工程原理,大多数FP不足为奇 语言提供了语法糖,使使用它们变得更容易-DAML是 没什么。

作为Functor接口实例的封装值支持 Party函数,DAML也为此函数提供了中缀运算符fmap

一个封装值,它是Monad接口的一个实例(称为 DAML中的<$>)支持Actionfmap和bind / flatMap函数。 DAML提供pure作为return的别名;和pure运算符 绑定/ flatMap。它还为>>=提供了do-notation作为语法糖,因此:

>>=

产生一个复合do t <- getTime a <- useTime t combineWithTime a t 值,该值(运行时)运行Update, 将结果值传递到getTime,然后将两个结果都传递给 useTime。此do块的结果也封装了combineWithTime值, 这样我们就不会破坏封装,因为在运行时 Update我们已经为封装提供了封装上下文 复合updateA/B/C值。

如果(如您在示例中所做的那样)我们使此Update阻塞了 选择,然后执行选择将运行复合更新。 另外,如果将其传递给do,则可以将其作为 场景。如果两者都不做(例如,如果您有 两个更新值,并使用if表达式在它们之间进行选择),然后 它不会产生可观察的效果,因为在DAML中,所有功能都是纯函数。