如何在 Dhall 中表示以下 JSON?
How to represent the following JSON in Dhall?
我使用以下 JSON 来表示我们的基础设施。这是一个大大简化的版本。
{
"us-east-1": {
"qa": {
"etcd": {}
}
},
"eu-central-1": {
"dev": {
"etcd": {}
}
},
"eu-west-1": {
"prod": {
"etcd": {}
}
}
}
这可以映射到文件夹,并且很容易从代码中处理。
#!/usr/bin/env python
import json
import os, sys
with open('infrastructure.json', 'r') as read_file: infra = json.load(read_file)
regions = infra.keys()
for region in regions:
stages = infra[region].keys()
for stage in stages:
apps = infra[region][stage].keys()
for app in apps:
os.makedirs(os.path.join('infra', region, stage, app), 0o750, exist_ok=True)
print('region: {}, stage: {}, app: {}'.format(region, stage, app))
但是,我想使用 Dhall 生成此文件以将可能的键限制为列表。
Dhall 对此有支持:
let AwsRegions : Type = < us-east-1 | eu-central-1 | eu-west-1 >
let Stages : Type = < dev | qa | prod >
let Applications : Type = < etcd | postgresql | hadoop >
唯一的问题是我找不到将记录键作为空类型的支持,只能将值限制为那些值。
这让我可以通过以下方式拥有我们的基础设施:
let infrastructure :
List { region: AwsRegions, stage: Stages,
applications: List Applications } =
[ { region = AwsRegions.us-east-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-central-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.qa,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.prod,
applications = [
Applications.hadoop,
Applications.etcd ] } ]
in infrastructure
生成的 JSON 从代码中处理起来有点困难,我不能像其他表示一样轻松地引用我们的基础设施的子集。
有没有办法让 Dhall 拥有像枚举(空类型的联合)这样的键?
这将是生成嵌套 JSON 键被限制为枚举的记录的惯用方式:
let keyValue =
λ(k : Type)
→ λ(v : Type)
→ λ(mapKey : k)
→ λ(mapValue : v)
→ { mapKey = mapKey, mapValue = mapValue }
let Prelude = https://prelude.dhall-lang.org/v11.1.0/package.dhall
let Application = < etcd | postgresql | hadoop >
let Applications = Prelude.Map.Type Application {}
let application = λ(application : Application) → keyValue Application {} application {=}
let Stage = < dev | qa | prod >
let Stages = Prelude.Map.Type Stage Applications
let stage = keyValue Stage Applications
let AwsRegion = < us-east-1 | eu-central-1 | eu-west-1 >
let AwsRegions = Prelude.Map.Type AwsRegion Stages
let awsRegion = keyValue AwsRegion Stages
in [ awsRegion AwsRegion.us-east-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-west-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.qa
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.prod
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-central-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
]
... 呈现如下 JSON:
$ dhall-to-json/dhall-to-json --file /tmp/test/example.dhall
{
"eu-central-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
},
"eu-west-1": {
"dev": {
"etcd": {},
"hadoop": {}
},
"prod": {
"etcd": {},
"hadoop": {}
},
"qa": {
"etcd": {},
"hadoop": {}
}
},
"us-east-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
}
}
我使用以下 JSON 来表示我们的基础设施。这是一个大大简化的版本。
{
"us-east-1": {
"qa": {
"etcd": {}
}
},
"eu-central-1": {
"dev": {
"etcd": {}
}
},
"eu-west-1": {
"prod": {
"etcd": {}
}
}
}
这可以映射到文件夹,并且很容易从代码中处理。
#!/usr/bin/env python
import json
import os, sys
with open('infrastructure.json', 'r') as read_file: infra = json.load(read_file)
regions = infra.keys()
for region in regions:
stages = infra[region].keys()
for stage in stages:
apps = infra[region][stage].keys()
for app in apps:
os.makedirs(os.path.join('infra', region, stage, app), 0o750, exist_ok=True)
print('region: {}, stage: {}, app: {}'.format(region, stage, app))
但是,我想使用 Dhall 生成此文件以将可能的键限制为列表。
Dhall 对此有支持:
let AwsRegions : Type = < us-east-1 | eu-central-1 | eu-west-1 >
let Stages : Type = < dev | qa | prod >
let Applications : Type = < etcd | postgresql | hadoop >
唯一的问题是我找不到将记录键作为空类型的支持,只能将值限制为那些值。
这让我可以通过以下方式拥有我们的基础设施:
let infrastructure :
List { region: AwsRegions, stage: Stages,
applications: List Applications } =
[ { region = AwsRegions.us-east-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-central-1,
stage = Stages.dev,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.qa,
applications = [
Applications.hadoop,
Applications.etcd ] },
{ region = AwsRegions.eu-west-1,
stage = Stages.prod,
applications = [
Applications.hadoop,
Applications.etcd ] } ]
in infrastructure
生成的 JSON 从代码中处理起来有点困难,我不能像其他表示一样轻松地引用我们的基础设施的子集。
有没有办法让 Dhall 拥有像枚举(空类型的联合)这样的键?
这将是生成嵌套 JSON 键被限制为枚举的记录的惯用方式:
let keyValue =
λ(k : Type)
→ λ(v : Type)
→ λ(mapKey : k)
→ λ(mapValue : v)
→ { mapKey = mapKey, mapValue = mapValue }
let Prelude = https://prelude.dhall-lang.org/v11.1.0/package.dhall
let Application = < etcd | postgresql | hadoop >
let Applications = Prelude.Map.Type Application {}
let application = λ(application : Application) → keyValue Application {} application {=}
let Stage = < dev | qa | prod >
let Stages = Prelude.Map.Type Stage Applications
let stage = keyValue Stage Applications
let AwsRegion = < us-east-1 | eu-central-1 | eu-west-1 >
let AwsRegions = Prelude.Map.Type AwsRegion Stages
let awsRegion = keyValue AwsRegion Stages
in [ awsRegion AwsRegion.us-east-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-west-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.qa
[ application Application.hadoop
, application Application.etcd
]
, stage Stage.prod
[ application Application.hadoop
, application Application.etcd
]
]
, awsRegion AwsRegion.eu-central-1
[ stage Stage.dev
[ application Application.hadoop
, application Application.etcd
]
]
]
... 呈现如下 JSON:
$ dhall-to-json/dhall-to-json --file /tmp/test/example.dhall
{
"eu-central-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
},
"eu-west-1": {
"dev": {
"etcd": {},
"hadoop": {}
},
"prod": {
"etcd": {},
"hadoop": {}
},
"qa": {
"etcd": {},
"hadoop": {}
}
},
"us-east-1": {
"dev": {
"etcd": {},
"hadoop": {}
}
}
}