vacationlabs / haskell-webapps

Proof-of-concept code for a typical webapp implemented in various Haskell libraries/frameworks
MIT License
134 stars 21 forks source link

reflex, servant-reflex - Initial sprint #37

Closed meditans closed 8 years ago

meditans commented 8 years ago

Description

The main aim of this sprint is translating a mock login page in idiomatic reflex-frp code.

In solving this problems three macro areas will be researched, to construct a solid foundation for future work in this area:

How to structure an app with interoperating client and backend

To simulate the interaction between the UI and the backend, I will write a mock servant API and server. Common solutions for project structure will be examined, and I'll document the best one with a simple project.

The validation problem

A special focus will be put in investigating the validation problem, both in Client and Server side. An optimal way to serve both needs will be researched.

The potentiality of the frp paradigm

The frp paradigm will be followed to its natural conclusion, using the servant-reflex library. I'll learn to use the library, and if it's acceptabtable, use it to write transparent code in the frontend. If not, the problems in this library will be documented and reported upstream.

Tech Stack

reflex, servant, servant-reflex

saurabhnanda commented 8 years ago

Quick overview of what servant-reflex solves?

meditans commented 8 years ago

Sure, I'll leave the link to the github repo, a quick description from the readme and some of my notes:

The problem servant-reflex solves

Keeping your frontend in sync with your API server can be difficult - when the API changes its input parameters or return type, XHR requests from the frontend will fail at runtime. If your API is defined by servant combinators, you can use servant-reflex to share the API between the server and frontend. Syncronization between is checked at compile time, and rather than building XHR requests by hand, API endpoints are available behind reflex's FRP semantics.

Additional notes

As far as I can see this library let you abstract from the specific calls to the API: the most importan function in this library is client, which takes your API and returns a series of functions, one for each end point, which manage serialization, XhrRequest generation, and deserialization. And the result is presented as a Dynamic behaviour:

A simple example adapted from the readme: the API

type API = "getint"  :> Get '[JSON] Int

produces a function of type:

   getint :: MonadWidget t m
          => Event t ()                  -- ^ Trigger the XHR Request
          -> m (Event t (ReqResult Int)) -- ^ Consume the answer

as you can see, getint is a function that, every time the event passed as a first argument fires, serializes the eventual input value (here there isn't one), makes a call to the server, deserialize the response, and presents the result of the API call as an Event.

saurabhnanda commented 8 years ago

Great! Let's get started!

saurabhnanda commented 8 years ago

@meditans congratulations on your first merge 👍

Just comment & close this issue with with:

meditans commented 8 years ago

What got done

A simple structure to permit an interoperating client and backend has been devised. The validation problem has been solved for simple cases, but we still have to find a coherent view on validation that scales (for example, the problem of how to match the error message to the place in the dom in which they were generated, for a large datatype). The servant-reflex library has been studied and put to use, and it was confirmed its elegance in the context of the reflex-frp ecosystem. I've also corrected some outdated online tutorials (like that on the reflex-platform page) to make simpler the learning of reflex-frp, and I'm in the process of contributing back to reflex some functions that I consider useful. I also managed to tackle the minification problem, which constitutes a pr in its own.

What got pushed to the next sprint

In general, the thing that remains to be done is devise a general system to talk about validations. We decided to tackle this problem in the context of a more complicate user interface, which will be the main focus of the next sprint.

Any interesting thoughts/learnings/issues

There are some main points I'd like to share here, to fix my memories for when we'll write something bigger: