Haskell on AWS Lambda
This post will demonstrate running Haskell on AWS Lambda.
Background
AWS allows running arbitrary binaries https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/ which we can use to write Lambda functions using Haskell.
Prerequisites
Hello World
Create a hello world Haskell binary.
The binary needs to be compiled for x86_64 / AWS Linux, see https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/.
mkdir -p lambda-test/src
file lambda-test/lambda-test.cabal:
-- Initial lamda-test.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/
name: lambda-test
version: 0.1.0.0
-- synopsis:
-- description:
-- license:
license-file: LICENSE
author: Adam Evans
maintainer: aevans@atlassian.com
-- copyright:
-- category:
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable lambda-test
ghc-options: -Wall
hs-source-dirs: src
main-is: Main.hs
build-depends: base >=4.8 && <4.9
default-language: Haskell2010
file lambda-test/Main.hs:
module Main where
main = putStrLn "Hello World Haskell"
Build the binary
I use Mac OS so need to build the binary using Docker to be compatible with the Lambda environment. If you develop on a Linux machine you can probably skip using Docker to build the binary.
cd lambda-test
docker run --rm -v "$PWD":/tmp/lambda -w /tmp/lambda thoughtbot/ghc \
/bin/bash -c "cabal sandbox init; cabal build"
Shim file
We will use the Lambda native Node.js support as a shim to invoke the Haskell executable.
file Main.js:
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];
var exec = require('child_process').execFile;
exports.handler = function(event, context) {
exec('./lambda-test', function(err, data) {
console.log(err);
console.log(data.toString());
context.done(null, data.toString());
});
};
Package the Lambda
Note -j
strips the directory path.
zip -r -j lambda-test.zip Main.js dist/build/lambda-test/lambda-test
Create the Lambda function
In the AWS console go to the Lambda section, click “Create Lambda Function”
On the Select blueprint page, click Skip at the bottom.
Configure
On the Configure page make sure Runtime is set to Node.js.
On code entry type select “Upload a .ZIP file” and upload the zip we created
On “Handler” change this to “Main.handler” to match the name of our Main.js file.
Test
After saving the function you can test it by clicking the “Test” button
You should see the below:

Extending
The event and context data passed to the Node.js handler function can be passed on to the Haskell executable as command line arguments.