Building Simple Authentication with Haskell and Elm — Part 1

Why Haskell and Elm?

I’ve been intrigued by functional programming languages for a long time. The idea of “If it compiles it usually works” when writing code excites me. Haskell and Elm both being strongly statically typed languages adhere to this. I have been trying to learn both of these for some time and have finally decided to create something which involves them both.

Goal

To create authentication workflow with Elm on the client side and Haskell for REST API.

Requirements

You will need following packages installed on your system for this:

Let’s dive right into it now!!

1. Create client and server folders

/app
/client
/server

2. Setup Elm Project

  • Installing webpack and loaders

We will be using webpack for compiling Elm to JavaScript and serving these files locally.

webpack-dev-server — for serving files locally

elm-webpack-loader — compiles Elm files

file-loader — for loading Html files

yarn add webpack webpack-dev-server elm-webpack-loader file-loader
  • Install elm module

elm-lang/html is the module we will need for writing Html in Elm

elm-package install elm-lang/html
  • Edit elm-package.json

Change source directory

"source-directories": [
"./src"
],
  • Create webpack config

client/webpack.config.js

  • Create index.html

Here we create our Html file wherein the elm-app will be embedded.

client/src/index.html

  • Create index.js

Next we embed our Elm-app to Html node with id “main”, that is present in index.html

client/src/index.js

  • Create Main.elm

Now we create a bare-bones file for our Elm application. We have five things here:

  • Model — This is how we store the state i.e. the structure of data we will be keeping for the page. Currently, we are keeping it simple and using just a String.
  • view — This method provides the view, how a page should look given an input model. Currently, we are displaying the model in a div tag.
  • Msg — Here we specify the type of messages we will be handling. Currently, this is just a stub.
  • update — This is used to handle any incoming messages from the page and to modify the model if need be. Currently, it is just a stub method which doesn’t do anything.
  • init — This is used to set up the initial page state. Currently, we are just setting the model as “Hello Elm”.

client/src/Main.elm

  • Modify package.json
{
...
"scripts": {
"start": "webpack-dev-server --port 3000",
"build": "webpack"
},
...
}
  • Test It
yarn start

Open http://localhost:4000 in browser and it should show “Hello Elm”.

3. Create Haskell project

  • Initialize cabal project
cabal init

Select Executable as output and src folder option for source directory.

Add scotty as dependency in server.cabal.

...
build-depends: base >=4.9 && <4.10
, scotty
...
  • Modify Main.hs

Here we create a server which listens on port 3000 with a get endpoint on root that returns plain text “Hello Haskell”.

  • Test it
cabal run

Open http://localhost:3000 in the browser and it should show “Hello Haskell”.

4. Make Elm talk to Haskell

  • Install elm-lang/http package for Elm
elm-package install elm-lang/http
  • Modify Main.elm

We add a few things to Main.elm to send a get request and process it.

Msg — We introduce a new type FetchResult which includes Result (Success/Failure) and Response of the request.

getData — We add a method to create the command for sending a request to our Haskell Server and retrieving the response as a String.

init — We call getData method to create request command to be sent.

update — We process both Ok and Err case for FetchResult and change the model accordingly.

  • Add CORS Support

We will need to change our Main.hs to use cors because server and client are on different domains.

Add wai-cors as dependency to server.cabal

...
build-depends: base >=4.9 && <4.10
, scotty
, wai-cors
...

Change Main.hs to

Now, you should see “Hello Haskell” on opening http://localhost:4000.

What’s Next?

In Part-2, we will be creating a form for user registration and JSON API to save the data.