Dhall-haskell: `yaml-to-dhall` is erratic with unions

Created on 3 Aug 2019  路  8Comments  路  Source: dhall-lang/dhall-haskell

$ cat U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >

Valid YAML, but inconsistent use of quoting:

$ dhall-to-yaml <<<'let U = ./U.dhall in U.x { x = Some 1 }'
x: 1
$ dhall-to-yaml <<<'let U = ./U.dhall in U.y { y = Some 1 }'
'y': 1

Correct:

$ echo 'x: 1' | yaml-to-dhall ./U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x { x = Some 1 }

Wrong:

$ echo 'y: 1' | yaml-to-dhall ./U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x
{ x = None Natural }
$ echo "'y': 1" | yaml-to-dhall ./U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x
{ x = None Natural }
jsoyaml

All 8 comments

$ yaml-to-dhall --version ''
1.4.0
$ dhall version
1.25.0

Similar behaviour is observed with json-to-dhall:

$ echo '{"x":1}' | json-to-dhall ./U.dhall 
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x { x = Some 1 }
$ echo '{"y":1}' | json-to-dhall ./U.dhall 
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x
{ x = None Natural }

The reason for the inconsistency in dhall-to-yaml's quoting is because YAML interprets an unquoted y as true, not the string/key 'y'. So dhall-to-yaml is actually behaving correctly here and protecting against the generated YAML being misinterpreted.

This is also the same reason why this example fails:

$ echo 'y: 1' | yaml-to-dhall ./U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x
{ x = None Natural }

Because y: 1 is not what you think it is! It's essentially the YAML version of [ { mapKey = True, mapValue = 1 } ].

However, you are right to be surprised about this behavior:

$ echo "'y': 1" | yaml-to-dhall ./U.dhall
< x : { x : Optional Natural } | y : { y : Optional Natural } >.x
{ x = None Natural }

The root cause behind that is because yaml-to-dhall does not have the --records-strict flag on by default. I actually found this behavior surprising, too, so I just fixed it yesterday in this pull request:

https://github.com/dhall-lang/dhall-haskell/pull/1181

... and indeed on master it gives the behavior you expected:

$ yaml-to-dhall '< x : { x : Optional Natural } | y : { y : Optional Natural } >' <<< "'y': 1"
< x : { x : Optional Natural } | y : { y : Optional Natural } >.y { y = Some 1 }

According to https://stackoverflow.com/a/42284910/1013393 only true, True, TRUE, false, False, and FALSE should be parsed as bools in YAML1.2. YAML1.1 bools like y or off should now be interpreted as strings.

@sjakobi: Maybe that will be fixed by #1248

This was indeed fixed by #1248! Thanks @vijayphoenix! :)

It might be a good idea to add regression tests, so we can ensure that this keeps working even with the aeson-yaml flag that I understand @patrickmn will introduce.

Agreed.

I plan to do a PR no later than the weekend.

This slipped my mind when I was adding the list of special strings (aeson-yaml will quote 'y'/'n'/'on'/'off').

Will submit a fix and regression test soon.


FYI this seems like a general issue:

https://github.com/go-yaml/yaml/issues/214

https://github.com/kubernetes/kubernetes/issues/34146#issuecomment-527974153

(Also, perhaps expectedly, when I remove the quoting of 'yes'/'no', my test to assert that libyaml decodes the original input fails.)

..but it seems reasonable to expect the Dhall user not to feed "yes" to Kubernetes.

Was this page helpful?
0 / 5 - 0 ratings