首先,我将采用一种不进行类型检查的方法作为激发解决方案的起点:
let rando = ComparisonOperator::{ Variable = "$.name", StringEquals = Some "Cow" }
let comparisons = renderRuleComparisons ComparisonType.Not [ rando ]
in comparisons # toMap { Next = "Public" }
toMap
是将记录转换为键值列表的关键字,并且#
是列表串联运算符。这Dhall 备忘单 https://docs.dhall-lang.org/howtos/Cheatsheet.html有一些如何使用它们的示例。
上述解决方案不起作用,因为#
无法合并具有不同元素类型的列表。的左侧#
运算符有这种类型:
comparisons : List { mapKey : Text, mapValue : Comparison.Type }
...而右侧#
运算符有这种类型:
toMap { Next = "Public" } : List { mapKey : Text, mapValue : Text }
……所以两个人List
由于 s 的类型不同,因此无法按原样合并mapValue
field.
有两种方法可以解决这个问题:
- 方法 1:只要存在类型冲突,就使用 union
- 方法 2:使用可以保存任意值的弱类型 JSON 表示形式
对于这个特定示例,方法 1 是更简单的解决方案,方法 2 是更通用的解决方案,可以处理非常奇怪的 JSON 模式。
对于方法 1,dhall-to-json
转换为 JSON 时,将自动剥离非空联合构造函数(留下它们所包装的值)。这意味着您可以转换两个参数#
运营商同意这种常见类型:
List { mapKey : Text, mapValue : < State : Text | Comparison : Comparison.Type > }
...然后您应该能够连接两个键值对列表并dhall-to-json
将正确渲染它们。
还有第二种用于处理弱类型 JSON 模式的解决方案,您可以在此处了解更多信息:
- Dhall 手册 - 如何将现有 YAML 配置文件转换为 Dhall https://github.com/Gabriel439/dhall-manual/blob/develop/manuscript/01-YamlToDhall.md
基本思想是,所有 JSON/YAML 集成都识别并支持弱类型 JSON 表示形式,该表示形式可以保存任意 JSON 数据,包括具有不同形状键的字典(如您的示例中所示)。您甚至不需要将整个表达式转换为这种弱类型表示;您只需将此表示形式用于遇到架构问题的配置子集。
对于您的示例来说,这意味着您可以将两个参数更改为#
运算符具有这种类型:
let Prelude = https://prelude.dhall-lang.org/v12.0.0/package.dhall
in List { mapKey : Text, mapValue : Prelude.JSON.Type }
The 的文档Prelude.JSON.Type https://github.com/dhall-lang/dhall-lang/blob/v12.0.0/Prelude/JSON/Type还有有关如何使用此类型的更多详细信息。