I’m pushing myself to learn Haskell, but I realized that the best way to learn is
to make things, broke them and build them again. So I decided to start a toy
project to create a substitute for commands like $ python3 -m http.server
or
$ php -S 0.0.0.0:8000
that fires a simple HTTP server to look your HTML files.
For this, I have a twitter thread
to log me and avoid procrastination.
To meet my goal, I must find a way to work with a web server like in other programming languages or better. Let’s find out what we can do for this.
Reference Implementation
So, let’s start with a reference implementation, and since JavaScript is widely in use this could be a good idea. On NodeJS we can walk through this with this snippet:
It’s self-explaining, we call for a module (line 1), define a server (lines 2-7) and start the server (line 8). For the project this is the kind of things I will like to do rather than going too low-level programming.
Using Sockets
For any project, we need a bit of research looking for options of how to do what we want, the Haskell Wiki has a page with a reference for creating Simple Servers, plus it is in a concurrent fashion.
Since we are using sockets
(line 5 withSocketsDo)
it’s clear that its lower level programming in comparison with our JavaScript reference.
If you still have doubts just see the line 15, and this string
"HTTP/1.0 200\r\nContent-Length: 13\r\n\r\nHello, World!\r\n"
rings the low-level
programming bell again.
Nothing bad with this kind of fine grain control, but is not the abstraction level I’m looking for. Anyway, it is worth to take a look at this example because even using sockets and other low-level abstraction resources Haskell still is a very expressive and concise.
Using Wai
Some more googling and I found Wai, a package of the Yesod framework. This is pretty much is what I expect to use for my project. To be honest this code and the reference one maybe are oversimplifications, but still, give us valuable information about how our application is going to deal with the web server.
To build this example you need to install two packages, since I use Haskell Stack you can do it writing:
$ stack install wai warp
or:
$ cabal install wai warp
if you use the cabal build tool.
A quick and dirty explanation of this code is, a language pragma to make strings
polymorphic (line 1), imports for modules and specific functions (lines 2-4),
a function definition for the application (lines 6-7) and finally a call for that
function at the main
entry point.
And this is all for now, hope you find this post useful.
Credits for the plane blueprints image to the Bureau of Aeronautics, U.S. Navy