Open saurabhnanda opened 5 years ago
ETypes
represent "type signatures", whereas ETypeDef
represent what the time is.
This library tries to write code for the user's type. The rationale was that when an endpoint returns Bool
, the user would just use the decoder from Elm
instead of generated code. Of course this doesn't work too well when generating code for whole APIs. ...
For your particular problem, I am afraid there is no great solution. It is indeed ETypePrimAlias that makes sense here, and it should alias to String
and Bool
on the Elm side.
I don't know if this terse answers help you, and I am personally open to PR. I am sure @agrafix is too :) I think this library might need a good rework to suit your needs though ...
One thing that would be nice would be a generic Elm AST pretty printer, instead of the terrible string manipulation that happen all over the place. Would you have that in your sleeves? :)
@bartavelle Thanks for the clarification on ETypeDef
vs EType
. I'll rephrase my understanding again:
EType
is trying to describe the structure of a new type that needs to be "written / generated" on the Elm sideETypeDef
is trying to specify which existing Elm type should correspond to a given Haskell typeA related question: any reason why EAlias
and ESum
contain only a subset of the fields of Aeson.Options
? Isn't it better to simply have the entire Aeson.Options
record as one of the fields?
So, conceptually, here's what is required (or may already be existing):
One thing that would be nice would be a generic Elm AST pretty printer, instead of the terrible string manipulation that happen all over the place. Would you have that in your sleeves? :)
This is probably the last thing that I'll attack. Upon a cursory glance, I wasn't able to find a "blessed" Elm code generator. Also, I'm also internally debating if it is better to stick to string-based templates for Elm code-gen to allow library users to modify them easily. For example, users might want an easy way to modify the Elm api-wrappers that will be generated.
For the option records, it is probably that those are parameters that have been added recently (or at least, recently enough), and that they are not supported by the library yet.
As for the difference between ETypeDef
and EType
I would have to read the code to tell you their exact meaning, so your guess is as good as mine right now ;)
I think I found something for safer Elm code gen - http://hackage.haskell.org/package/language-elm
That would be perfect!
@saurabhnanda we're also interested into this, alongside with https://www.reddit.com/r/haskell/comments/9zq14v/state_of_servantelm/
@domenkozar Could you check out the issue I opened here? https://github.com/agrafix/elm-bridge/issues/41
I'm not too familiar with how people are using elm-export
or elm-bridge
, and what their short comings are, but it's possible a sturdier core could help move things along.
@agrafix @bartavelle is it alright if we use this thread to discuss evolution of this library?
I've gotten a basic POC of using Servant.Foreign
to generate an Elm API for a given Servant API. However, I am unable to come up with a good analog for the ToHttpApiData
& FromHttpApiData
type-classes of Servant. IIUC any type being "injected" in the URL (either as a path-segment OR as a query-param) needs to implement these type-classes to convert values of that type to/from Text
.
How does one implement something like this, fairly automagically on the Elm side? Challenges:
toString
has been moved to Debug
and will not be available once you build the Elm project for production. Otherwise one possible solution could've been to use toString
-- but it may not parse correctly on the Haskell side.toUrlSegmentBool
, toUrlSegmentDouble
, toUrlSegmentInt
, toUrlSegmentTime
, toUrlSegmentUTCTime
, etc. But this would need to be manually kept in sync with Haskell code at http://hackage.haskell.org/package/http-api-data-0.4/docs/src/Web.Internal.HttpApiData.html#ToHttpApiData - which mostly uses show
instances for all the common types.newtype PK a = PK Int
, and they're using in URL segments a lot. GET /users/:userId
. How many different toUrlSegment*
functions, on the Elm side, would one need to define to handle something like this?/cc @domenkozar @mitchellwrosen
servant-elm
currently does the following...
... but has implemented a hard-coded list of type <=> string conversion functions for 0.19:
https://github.com/mattjbray/servant-elm/pull/45/files#diff-7e13462cc66d19b6a0d2a0ddcd7e8864R494
Okay! I've got a PoC in place which can do the following...
...given the following Servant API...
data Routes route = Routes
{ rRunCode :: route :- "runCode" :> "randomUrlSegment" :> Capture "id" Int :> Capture "order" String :> QueryParam "tryingEither" (Either Int Bool) :> QueryParam "someOtherParam" Bool :> ReqBody '[JSON] (Maybe InterpreterInput) :> Post '[JSON] InterpreterOutput
} deriving (Generic)
... it generates the following Elm API wrapper...
postrunCoderandomUrlSegmentbyidbyorder : Msg -> Int -> String -> Maybe (Either (Int) (Bool)) -> Maybe (Bool) -> Maybe (InterpreterInput ) -> Cmd Msg
postrunCoderandomUrlSegmentbyidbyorder msg0 id3 order4 tryingEither5 someOtherParam6 body8 =
Http.post { url = Url.absolute ["runCode", "randomUrlSegment", String.fromInt id3, identity order4] <| List.filterMap identity [toUrlSegmentMaybe (toUrlSegmentEither (String.fromInt) (toUrlSegmentBool)) tryingEither5, toUrlSegmentMaybe (toUrlSegmentBool) someOtherParam6], body = Http.jsonBody <| jsonEncMaybe (jsonEncInterpreterInput) body8, expect = Http.expectJson msg0 jsonDecInterpreterOutput}
Shall I bring this into a PR-able form? Are you alright with introducing a dependency on servant
?
I personally use servant anyway, and I suppose most people do (?). It would be nice to ask @agrafix though, as he perhaps still uses this project?
@agrafix has been awfully quiet lately. Is he online on IRC / Reddit these days?
RE: Elm and http-api-data
I have hit the same issue and it's possible to use generics, but as soon as there is a manual instance in Haskell, something like http://blog.stermon.com/articles/2018/04/09/elm-stringeable-types-library-for-elm-019.html would work.
No idea! To be honest, I do not use this package anymore either, as I have stopped using Elm. I will try to keep maintaining it, and have a couple things to do on it, but this will have to wait for January ...
@bartavelle Moved on to PureScript? :)
@mitchellwrosen moved out of frontend, but last personal project was purescript + wasm indeed ;)
I'm extending this library to auto-generate Elm API wrappers based on Servant type-signatures [1]. I've pretty much wrapped my head around the internals, but am scratching my head over the following:
ETypeDef
andEType
. It seems to me thatEType
is some sort of Elm-compatible subset ofTH.Type
, but I'm not so sure aboutETypeDef
.deriveElm
uses TH to generate instances forIsElmDefinition
. However, there are noIsElmDefinition
instances for things likeString
orBool
. It this because you don't want to have "global" Haskell <=> Elm type-mappings forced upon users of this library, allowing them, instead, to make a choice on a case-by-case basis by usingmakeModuleContentWithAlterations
infra?IsElmDefinition
for my app, how would I do that for something likeString
/Bool
? How does one write a sensible implementation forcompileElmDef :: Proxy a -> ETypeDef
? What value should this function return? The only possible option isETypePrimAlias
, but I'm not sure how that would work? (this should give you some context about why I'm asking the very first question).[1] Btw, are you open to a PR for this functionality? I don't see the point in releasing yet another elm <=> haskell library.