如何使包含数据的递归Dhall sum类型

时间:2020-05-12 00:00:20

标签: dhall

这是我的示例代码。我一直无法弄清楚如何使我的State求和类型递归,但仍然允许它像在其他地方用作求和类型一样。我的StateMachine类型也是如此。

let State =
      < Task : { Comment : Text, Resource : Text, End : Bool }
      | Map : { Comment : Text, Iterator : StateMachine }
      | Parallel : { Comment : Text, Branch : List State }
      >

let StateMachine
    : Type
    = { Comment : Optional Text
      , StartAt : Text
      , States : List { mapKey : Text, mapValue : State }
      }

let test
    : StateMachine
    = { Comment = Some "A simple minimal example"
      , StartAt = "Hello World"
      , States =
        [ { mapKey = "Hello World"
          , mapValue =
              State.Task { Type = "Task", Resource = "Test", End = True }
          }
        ]
      }

in  test

是否有一种合理的方法来做到这一点,而又不会浪费代码的大小并使最终用户导入和使用的类型符合人体工程学?如果从示例中看不出来,我将尝试设置状态机。

我尝试了以下操作,但是遇到State.Task的“不是记录或联合”错误:

let State
    : Type
    =   ∀(_State : Type)
      → ∀(Task : { Type : Text, Resource : Text, End : Bool })
      → ∀(Map : { Type : Text, Iterator : _State })
      → _Stat

1 个答案:

答案 0 :(得分:1)

首先,我相信您想说的类型是:

let State
    : Type
    = ∀(State : Type) →
      ∀(Task : { Type : Text, Resource : Text, End : Bool } → State) →
      ∀(Map : { Type : Text, Iterator : State } → State) →
        State

in  State

要回答您的问题,最接近递归联合类型的就是这种等效表示形式:

let State
    : Type
    = ∀(State : Type) →
      ( < Task : { Type : Text, Resource : Text, End : Bool }
        | Map : { Type : Text, Iterator : State }
        > →
          State
      ) →
        State

in  State

...但是您不会免费获得联合构造函数,因此无论如何我都不建议使用后一种表示形式。

对于这两种方法,您都必须创建行为与构造函数相同的函数。这种语言不会像非递归联合类型那样为您生成它们。

我将说明如何编写第一种类型的构造函数,因为这是我建议使用的表示形式:

let Types =
      let Task = { Type : Text, Resource : Text, End : Bool }

      let Map = λ(State : Type) → { Type : Text, Iterator : State }

      let State
          : Type
          = ∀(State : Type) →
            ∀(Task : Task → State) →
            ∀(Map : Map State → State) →
              State

      in  { Task, Map, State }

let -- Record of constructors similar to what you would get from a union type
    State =
      let Task
          : Types.Task → Types.State
          = λ(x : Types.Task) →
            λ(State : Type) →
            λ(Task : Types.Task → State) →
            λ(Map : Types.Map State → State) →
              Task x

      let Map
          : Types.Map Types.State → Types.State
          = λ(x : Types.Map Types.State) →
            λ(State : Type) →
            λ(Task : Types.Task → State) →
            λ(Map : Types.Map State → State) →
              Map (x with Iterator = x.Iterator State Task Map)

      in  { Task, Map }

in  State.Map
      { Type = "Foo"
      , Iterator = State.Task { Type = "Bar", Resource = "CPU", End = False }
      }

有关更多详细信息,请参见: