makeHaskellTypeFromUnion and fields with sum types

I noticed that makeHaskellTypeFromUnion fails for the following type defined in Stuff.dhall:

{ title : Text 
, value : < Foo : Text | Bar : Text >
}
makeHaskellTypeFromUnion "Stuff" "< Stuff : ./Stuff.dhall >"

The error message is “Unsupported simple type”, which is described further in the source indicating that the sum type here (used in value) is not supported by the TH code.

Is there any way to get this to be working, though? Or would it require a PR to support non-simple types in makeHaskellTypeFromUnion?

1 Like

@srid: The main reason that fields are currently restricted to simple types is because they are anonymous. If the type of a field requires a new Haskell datatype definition then that definition needs to be named.

One possible solution might be to auto-generate names for nested types (e.g. Stuff0, Stuff1, …)

The actual dhall code actually labels them:

let SomeType = ./SomeType.dhall
in
{ title : Text
, value : SomeType
}

But I suppose variables names are not really stored in the Dhall AST? If that’s the case I wonder if there is some way to “tag” the anonymous types. If nothing else, perhaps the TH function can be made to take in explicit arguments? Like:

makeHaskellTypeFromUnion 
  "SomeType" "./SomeType.dhall" [] 
makeHaskellTypeFromUnion 
  "Stuff" "< Stuff : ./Stuff.dhall >" [("./SomeType.dhall", "SomeType")]

@srid: I think the cleanest solution would be to provide a makeHaskellTypes function which accepts several let bindings like what you already have and turns each one into a datatype definition

1 Like

That sounds like a better approach. By the way, here’s the real word code where I needed this: https://github.com/srid/website/blob/45b6cd0895661643246f613fdac1b16c555b724b/src/Website/Tidbit.hs#L27-L66

You will see three types. The Tidbit type in particular could not be generated by TH because it uses TidbitContent. Both types also use a newtype over Text (called Markdown), and one as well uses a newtype over Day[1]. I think this is another area where makeHaskellTypes can be improved; i.e., allow Text in a .dhall spec but use the specified newtype in the Haskell generated code (Markdown and Day in this case).

[1] There is a newtype over Day here only because Dhall does not have a day type, so I “parse” the text as Day in the FromDhall instance.

1 Like

@srid: I have a pull request up implementing support for multiple top-level Dhall types that can refer to one another:

@srid: Regarding newtype support, I think a simpler way to do that on the user end is to:

  • let the code generation generate the newtype-free version
  • have the user define a parallel set of types with the desired newtypes
  • Use coerce to convert between the two (which should succeed if they are the same modulo newtype conversions)

@Gabriel439 Nice! I’m trying your PR. Regarding newtype, that approach you indicated will only work if the newtype is over simple types already supported by Dhall, whose TH doesn’t support mapping to user-defined types or some Haskell library types like Day.

I’ll draft a PR of my repo based on your PR, and have its code better illustrate this problem regarding newtypes.

EDIT: I’ll leave further comments regarding that in your PR.