Template Haskell with NonEmpty lists

I’m generally clueless about TH but I’m trying to be good and use it to keep my types from getting out of sync between Dhall and Haskell. However, I have nonempty lists in my Dhall in the form { head : a, tail : List a }, and this precludes me from using makeHaskellTypes for any of my Dhall types that have such nonempty lists as fields.

Is there any way to get makeHaskellTypes to recognize fields of that form as NonEmptys? Just making a FromDhall instance for NonEmpty isn’t enough. I’m unsure if I could even write a NonEmpty newtype as I don’t know if makeHaskellTypes will work for * -> * kinds, and having to make a bunch of different NonEmptyInts, NonEmptyNaturals, NonEmptyText types everywhere would hopelessly clutter the Haskell side of things.

1 Like

@SiriusStarr: Using the current API there isn’t really a good way to do this for user-defined higher-kinded types. You can find the logic for generating Haskell types from Dhall types here:

https://hackage.haskell.org/package/dhall-1.38.0/docs/src/Dhall.TH.html#local-6989586621680086781

… and basically it only supports:

  • Bool
  • Double
  • Integer
  • Natural
  • Text
  • List a (if a is supported)
  • Optional a (if a is supported)
  • Any monomorphic type provided as one of the inputs to makeHaskellTypes

If we were to amend the API to support this, there are two main ways that I can see for doing this:

  • Change makeHaskellTypes so that the code field of the HaskellTypes can be a function (i.e. code = "λ(a : Type) → { head : a, List a }" for the entry corresponding to NonEmpty lists) and it auto-detects this and handles it gracefully
  • Parametrize makeHaskellTypes on the logic for generating Haskell types from Dhall types and export the internal toNestedHaskellType function

Thanks for the response. Just wanted to make sure I wasn’t missing some solution at the moment.

The former is probably the more user-friendly solution, of course, but (not being familiar with TH), I’m not certain how much of a challenge it would be to implement. The latter is presumably more potentially customizable/powerful, however, if less convenient, perhaps?