The original intention of Fay is to use Haskell on the client side. If you use a Haskell web framework such as Yesod or Snap, using Fay you can use the same language on both client and server sides and some code can actually be shared.

However, because Fay is simply a subset of Haskell that compiles to JavaScript with no dependencies on the client side, you can use it on the server side too in combination with Node.js. I am not saying it is actually a good idea to write server code in Fay, but it is at least fun to investigate the feasibility. Here is a web server example written in Fay.

{-# LANGUAGE EmptyDataDecls #-}moduleHellowhere

EmptyDataDecls is required because JavaScript types are represented by empty data declarations in Fay.

import FFI

FFI module provides a foreign function interface.

dataHttpdataHttpServerdataRequestdataResponse

Http, HttpServer, Request and Response are JavaScript types we use in this example. They are represented by empty data declarations.

requireHttp ::FayHttp
requireHttp = ffi "require('http')"

This is a simple example of a FFI declaration. It returns the result of require('http') as a Http instance. Fay is a monad which is similar to IO monad. Because a FFI function often has side effects, Fay monad is used to represent this.

These FFI declarations use %1, %2 that corresponds to the arguments we specify in the type. Most Fay types are automatically serialized and deserialized. Note that we can only use point free style in FFI functions.

main is the entry point to our web server example. Its return type is Fay () because a Fay program can’t do anything without interacting with the world outside. Because we already wrapped all the Node.js APIs we use, we can program as if we write a normal Haskell program.

Compare our Fay web server program with the original Node.js program. Except for the FFI bindings, the main code is almost the same as before. However, our version is much more type-safe!