Creating a union of records with defaults


#1

I’m new to Dhall and I’m trying to model some of my existing YAML configuration.

I have an object called Action, which has a name and a command; depending on the command, it has other, additional fields. For example if command is “upload”, the additional field is “source”, and if the command is “run”, the additional field is “exec”.

I need to be able to provide a List of Actions, so I thought I would model each Action as a record with default values, then make a union to wrap the actions, then create a record which specifies the actions; something like the following:

let UploadAction = {
  Type = {
    name: Text,
    cmd: Text,
    source: Text
  },
  default = { cmd = "upload" }
}

let RunAction = {
  Type = {
    name: Text,
    cmd: Text,
    exec: Text
  },
  default = { cmd = "run" }
}

let ActionTypes : Type = < upload : UploadAction.Type | run : RunAction.Type >

let Package : Type = {
  name: Text,
  actions: List ActionTypes
}

let pkg : Package = {
  name = "Package test",
  actions = [
    ActionTypes.upload :: {
      name = "upload test",
      src = "bin/file"
    }
  ]
}

There are a few issues here. I’m not sure about using “.Type” in the union, but it seems to be required to avoid a syntax error. Then, in the list “Package.actions”, I’m unsure how to correctly specify the type of the union arm I’m attempting to create. I’m attempting to use the defaults so that I don’t need to specify the “cmd” argument in each action.

As is, this gives me “expression doesn’t match annotation” if I attempt to just use UploadAction in my actions list, or “the completion schema must be a record” if I use exacly the code pasted here (which sort of makes sense, as I declared the union with the Type, not the record).


#2

Hi, when using union, I think you need to specify the branch like so:

name = "Package test"
actions = [ ActionTypes.upload UploadAction::{=} ]

Also you example needs to use source instead of src


#3

Wow, that looks like it was the sole problem, great catch.

Is there somewhere in the documentation I would’ve seen this? I’ve been using a few of the resources linked from dhall-lang like Learn Dhall in Y minutes and Dhall.Tutorial but I never saw syntax like that.

Also, are there any ways to condense that syntax? It’s a bit bizarre looking to need both the union name as well as the record name.


#4

Not sure where this should fit in the documentation, but here is what Gabriel suggested to do for a similar problem: https://stackoverflow.com/questions/58782992/what-is-the-dhall-idiomatic-way-to-associate-different-schemas-to-union-values

E.g. create a transformUploadAction function to add the ActionTypes.upload branch prefix.