Сначала я включу подход, который не проверяет тип в качестве отправной точки, чтобы мотивировать решение:
let rando = ComparisonOperator::{ Variable = "$.name", StringEquals = Some "Cow" }
let comparisons = renderRuleComparisons ComparisonType.Not [ rando ]
in comparisons # toMap { Next = "Public" }
toMap
- это ключевое слово, которое преобразует записи в списки ключ-значение, #
- оператор объединения списков. Dhall CheatSheet содержит несколько примеров того, как использовать их оба.
Приведенное выше решение не работает, поскольку #
не может объединять списки с различными типами элементов. Левая часть оператора #
имеет такой тип:
comparisons : List { mapKey : Text, mapValue : Comparison.Type }
... тогда как правая часть оператора #
имеет этот тип:
toMap { Next = "Public" } : List { mapKey : Text, mapValue : Text }
... поэтому два List
не могут быть объединены как есть из-за разных типов поля mapValue
.
Существует два способа решения этой проблемы:
- Подход 1: Используйте объединение всякий раз, когда возникает конфликт типов
- Подход 2: Используйте представление со слабым типом JSON, которое может содержать произвольные значения
Подход 1 более простое решение для этого конкретного примера и подхода 2 - это более общее решение, которое может обрабатывать действительно странные схемы JSON.
Для подхода 1 dhall-to-json
автоматически удалит непустые конструкторы объединения (оставляя позади значение они оборачивали) при переводе на JSON. Это означает, что вы можете преобразовать оба аргумента оператора #
для согласования этого общего типа:
List { mapKey : Text, mapValue : < State : Text | Comparison : Comparison.Type > }
... и тогда вы сможете объединить два списка пар ключ-значение и dhall-to-json
отобразит их правильно.
Существует второе решение для работы со слабо типизированными JSON схемами, о котором вы можете узнать подробнее здесь:
Основная идея c заключается в том, что все интеграции JSON / YAML распознают и поддерживают слабо типизированное представление JSON он может содержать произвольные данные JSON, включая словари с ключами различной формы (как в вашем примере). Вам даже не нужно преобразовывать все выражение в это слабо типизированное представление; вам нужно использовать это представление только для подмножества вашей конфигурации, где вы сталкиваетесь с проблемами схемы.
Для вашего примера это означает, что вы должны изменить оба аргумента на оператор #
, чтобы иметь этот тип :
let Prelude = https://prelude.dhall-lang.org/v12.0.0/package.dhall
in List { mapKey : Text, mapValue : Prelude.JSON.Type }
Документация для Prelude.JSON.Type
также содержит более подробную информацию о том, как использовать этот тип.