【问题标题】:Trouble using the getTime function使用 getTime 函数时遇到问题
【发布时间】:2019-02-20 17:51:32
【问题描述】:

我在合同选择的断言语句中使用 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 不返回“时间”类型的值吗?什么是“mo 时间”?

【问题讨论】:

    标签: monads daml


    【解决方案1】:

    getTime 仅作为有账本时间概念的交易的一部分才有意义。 m0 是一个类型变量,它引用 UpdateScenario,具体取决于您的上下文。实际上,这仅仅意味着您需要将getTime 的结果绑定到do 块内的变量:

    do
      currentTime <- getTime
      assert ( startCoverage > currentTime )
    

    【讨论】:

      【解决方案2】:

      tldr: 根据@bame,您需要将getTime 的结果绑定到UpdateScenario 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 中,所有函数都是纯函数。

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

      getTimeFunc 是一个接受Unit 类型参数的函数,它 意味着只有一个参数可以传递给它:()。因为 函数是纯的,这意味着它不能考虑它之外的任何东西 参数,所以这个函数也必须返回一个常量值。事实上 getTimeValuegetTimeFunc 之间的唯一区别是您必须 通过getTimeFunc() 获取常量。

      封装

      存在一个你认为有“当前时间”概念的外部世界 can interrogate and use 是一个“上下文”,表示使用的任何函数 这不能再完全用输入 -> 输出来描述。 这被描述为“不纯”。

      在 DAML 中所有函数都是纯函数,所以如果我们想处理“杂质”,我们有 将杂质封装在纯值中。在 DAML 中,我们表达了这一点 封装为一种类型:

      encapsulatedImpureValue : m a
      
      

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

      encapsulatedImpureTimeValue : m Time
      

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

      getTime : (HasTime m) => m Time
      

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

      使用封装值

      我们现在可以写:

      let now = getTime
      

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

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

      1. DAML 模块中的每个顶级场景值都将由 DAML 运行 解释器作为 DAML 测试。

      2. 每个 DAML 模板选择的主体定义为 Update 值 将在执行选择时运行。

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

      组合封装值

      有许多标准 API 几乎为所有人所共有 用于将封装值组合成复合的函数式语言 价值观。你会听说过最著名的:“Functor”和“Monad” 这些定义了采用封装值和函数的函数,以及 以各种方式组合它们。封装就是这样一个基础软件 工程原理,大多数 FP 应该不足为奇 语言提供了语法糖来使这些更容易使用——而 DAML 是 没有什么不同。

      作为 Functor 接口实例的封装值支持 fmap 函数,DAML 还为其提供了中缀运算符&lt;$&gt;

      作为 Monad 接口实例的封装值(称为 Action 在 DAML 中),支持 fmappure 和 bind/flatMap 函数。 DAML 提供return 作为pure 的别名;和 &gt;&gt;= 运算符 绑定/平面图。它还为 &gt;&gt;= 提供了 do-notation 作为语法糖,所以:

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

      产生一个复合 Update 值,(当它运行时)运行 getTime, 将结果值传递给 useTime 然后将两个结果传递给 combineWithTime。这个do-block的结果也封装了Update值, 所以我们不会破坏封装,因为当我们运行时 updateA/B/C 我们已经为封装提供了封装上下文 复合Update值。

      如果(就像您在示例中所做的那样)我们将 do 设置为块 选择,然后执行选择将运行复合更新。 或者,如果我们将它传递给submit,我们可以将它作为 设想。如果您都不做(例如,如果您有 两个更新值,并使用 if 表达式在它们之间进行选择),然后 它不会产生明显的影响,因为在 DAML 中所有函数都是纯函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-17
        • 2012-09-21
        • 1970-01-01
        相关资源
        最近更新 更多