如何制作包含数据的递归 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

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

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 }
}

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

  • 如何将递归代码转换为 Dhall

最新更新