agrafix / elm-bridge

Haskell: Derive Elm types from Haskell types
BSD 3-Clause "New" or "Revised" License
100 stars 27 forks source link

Higher Kinded Data #61

Open runebak opened 4 months ago

runebak commented 4 months ago

Thank you for the great work on this library. Indispensable in keeping my Haskell types in sync with the front end types in elm.

I'm am using this library via servant-elm. In the backend I use beam, where types are required to look like

data UserT f = User
  { id :: C f Int32
  , name :: C f Text
  }

and since type C Identity a = a then type User = UserT Identity is equivalent with

data User = User
  { id :: Int32
  , name :: Text
  }

I can derive FromJson, ToJson from the aeson library and ToSchema from the openapi3 library for both User types above. However I can't find a way to derive a sensible IsElmDefinition for the type alias version? It should not include the f parameter. Is this possible, or what needs to be done to make this possible? Right now my workaround is doubling every higher kinded type with a simple type that I can derive IsElmDefinition for, but that seems do defeat the purpose.

runebak commented 4 months ago

After posting I realized that using the aeson library I actually cannot derive json for the type alias version above using template haskell. I didn't realize because I use generics to derive json. So maybe this is the issue.

bartavelle commented 4 months ago

Not saying this is impossible, but it would require special casing for the library. Not sure how I would do that in a way that is generic. Too bad we can't have annotations at the member site like in Rust to specialize stuff.

runebak commented 4 months ago

Thank you for getting back on this. Sounds like it is not an easy fix. But since I can derive sensible ToSchema it should be possible. Perhaps using generics, or I also thought of deriving the IsElmDefinition directly from the swagger-specification to have fewer sources of truth in the application. Right now I simply doubled all the types in the application and as this approach works for us right now, I'm not going to attack this problem at the moment.

bartavelle commented 4 months ago

By the way, can you make do with this function ? You can pass a lambda where you can alter Elm types

runebak commented 1 month ago

Hi Again. Sorry for getting back so late. Thank you for your suggesting of post-processesing the types instead. It actually works! You need to

  1. deriveElmDef defaultOptions ''UserT
  2. Use the User alias above in the api.
  3. Use generateElmModuleWith to generate code for your api altering the ElmOptions to Remove T and f from the ETypeDefs and remove T and Identity from the ETypes.

It is a little fragile though as it depends on using the naming convention from the beam tutorial. I'd still prefer to generically derive the right types. Maybe I'll get back to this. Until then, I'll do as above.

I have working code for this hack if anybody is interested :-)