Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert union alternatives to directory tree #1757

Merged
merged 1 commit into from
Apr 23, 2020

Conversation

sysvinit
Copy link
Collaborator

This change adds the ability to convert union alternatives with non-nullary constructors of appropriate type into directory trees.

The commit message describes the details of the change, but my motivation here is that I'd like to build s6-rc service directories using Dhall as a source format. The s6-rc service directory format is described here.

There are three types of s6-rc service directory: "longrun", "oneshot" and "bundle". I've modelled these as below (with some simplification and details omitted for brevity):

let Longrun : Type
    = { run : Text
      , finish : Optional Text
      , down : Optional Text
      }

let Oneshot : Type
    = { up : Text
      , down : Optional Text
      }

let Bundle : Type
    = { contents : Text }

I've then defined a Service type, which is a sum type over the above types.

let Service : Type = < L : Longrun | O : Oneshot | B : Bundle >

I'd like to be able to construct an expression of the Service type for each service in my database, and construct a record representing the database, e.g.:

let networkUp = Service.O { {- oneshot definition... -} }
let httpd = Service.L { {- longrun definition... -} }
in { httpd = httpd, networkUp = networkUp }

At this point it would be really convenient to feed the record definition into dhall to-directory-tree in order to automatically generate the service database directory tree, however the union type means that (without the change in this commit) I need to convert the Service type into some suitable record type, with only (Optional) Text fields, and not all combinations of these fields may be valid.

Hence, it would be really useful for my case to be able to convert (appropriately-typed) union types into directory trees.

This only works for alternatives with suitable non-nullary constructors. For
example, running `dhall to-directory-tree` on this expression:

    let UnionType : Type = < Left : Text | Right : Text >
    in { foo = UnionType.Left "one", bar = UnionType.Right "two" }

will result in the output directory containing two regular files, `foo` and
`bar`, with the contents "one" and "two", respectively.

The following union type, however, cannot be converted to a directory tree:

    let UnionType2 : Type = < Left : Text | Middle | Right : Text>

because the nullary `Middle` constructor has no associated value.

This change is of particular use when dealing with union types whose
constructors take values of differently structured types:

    let Thinkpad : Type = { series : Text, model : Text }
    let MacBookPro : Type = { year : Text }

    let Laptop : Type = < TP : Thinkpad | MBP : MacBookPro >

    let flywheel : Thinkpad = { series = "T", model = "460" }
    let splinch : MacBookPro = { year = "2007" }

    let myLaptops = {
        flywheel = Laptop.TP flywheel,
        splinch = Laptop.MBP splinch
    }

    in myLaptops

With this change, the above expression can be converted into the following
directory tree:

    <output dir>
    |- flywheel
    |  |- series
    |  \- model
    \- splinch
       \- year

Previously, this would have required creating a record structure which had an
`Optional Text` field for every possible member, something like:

    let Laptop2 : Type = { series : Optional Text, model : Optional Text
                         , year : Optional Text }

which has the issue that it would be possible to introduce an invalid instance
of the `Laptop2` type.
Copy link
Collaborator

@sjakobi sjakobi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me.

@Gabriella439 Gabriella439 merged commit 6d41db2 into dhall-lang:master Apr 23, 2020
@Gabriella439
Copy link
Collaborator

@sysvinit: Thank you for contributing this! 🙂

@sysvinit sysvinit deleted the unions-to-directory-tree branch April 23, 2020 09:04
@sysvinit
Copy link
Collaborator Author

Thanks for merging this! Do you have any idea when the next release (including this change) is likely to happen?

@Gabriella439
Copy link
Collaborator

@sysvinit: We typically release monthly, so around May 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants