In Part 1 of this series, I had something basic up and running: an Elm front-end talking to a Haskell back-end. The next step is to get some persistence out of the back-end. We need Haskell to talk to a database. The tutorial I was following went with a simple Sqlite interface, but I wanted to go full-bore with the whole type-safety and type system magic thing, so I decided to jump straight into Persistent.
TLDR; you can find the code I had by the end of this post here.
Before I could start working on the database stuff, I wanted to get more organized, and get some more niceties in place. First, I found a simple middle-ware drop in to deal with the cross-origin request stuff. The diff for adding this is dead simple, as seen in this commit. Just add the dependencies, create a simple settings type object, make a middle-ware function out of it, and stick in between the app and the server.
I did some renaming here, then I added in a plain file server here to serve the front-end. I reorganized things, pointed the front-end to the new route, and created an index.html file to make the single server work here.
At this point I spent a decent amount of time trying to wrap my head around persistent, and exactly how I could weave it through my already existing app. I think it was a little easier than it first seemed, but even still my first attempt had a whole bunch of extra types and stuff than were probably needed, and I even took out the CORs middle-ware since I was having trouble figuring out the whole composition and monadic manipulation thing.
By the time I was done, the back-end was not much more complicated than it started out as. A couple of things I learned were that the Persistent Entity type comes with a ToJSON instance built in, using the right types for the API specification made the end point handlers dead simple, and I’m starting to get a better feel for doing monadic and monoidic composition.
There was even a bonus by the time I was done with the back-end code. The only thing I had to change on the front-end was one type declaration in the JSON decoder because now it was
id instead of
It also looks the only place that will need to change in order to connect to an actual database is the mkApp function. I’m pretty sure it could even select what database to connect to based on the run-time environment and not cause any problems. I’m thinking of using an in-memory, Sqlite database for the development environment, and connecting to a PostgreSQL database in production.
Stay tuned for the next step of getting the front-end types to be generated from the back-end API spec. Should be fun.