70: Haskell Serverless - JSToElm
All Episodes

70: Haskell Serverless

After we've spent a comical amount of time getting a Linux environment setup it's time to actually try to get Haskell running on aws lambda.

Finally Ready to Go

  • We’ve got our environment all set up so let’s get going!

  • Steps

    • A new stack project using the template
    • stack new my-haskell-lambda https://github.com/theam/aws-lambda-haskell-runtime/raw/master/stack-template.hsfiles --resolver=lts-12.13 --omit-packages
    • Say it with me “stack is not like NPM, it is NOT a package manager” stack handles the management of your tool-chain.
    • resolver ?

    Specifies which snapshot is to be used for this project. A snapshot defines a GHC version, a number of packages available for installation, and various settings like build flags. It is called a resolver since a snapshot states how dependencies are resolved. There are currently four resolver types:

  • omit-packages ? this leaves the extra-depsflag commented out in the stack.yml
  • Added to stack.yml
packages:
- .

extra-deps:
- aws-lambda-haskell-runtime-1.0.9
  • initially I had only added the extra-deps. I didn’t realize that having added --omit-packages I still needed to add packages .
  • running make and we’re off to the races Progress 0/111
aws lambda create-function --function-name lambda-haskell \
--zip-file fileb://build/function.zip --handler src/Lib.handler \
--layers arn:aws:lambda:us-west-2:785355572843:layer:haskell-runtime:2 \
--runtime provided --role arn:aws:iam::XXXXXXXXXX:role/lambda-haskell-role
  • Oh man. needed
  • Success it’s been deployed.
  • Let’s see if it works on the first try…
  • NOPE execute failure. :cry:
  • Oh well, we spelled the handler wrong. AND
  • we had the wrong ‘Layer ARN’ This is the custom runtime, once we updated it to match the read me file, we had
  • :rocket: Lift Off!!

Can we update the code ?

aws lambda update-function-code --zip-file fileb://build/function.zip --publish --function-name lambda-haskell

HELL YES we can.

OK. So what did we actually deploy ? Let’s walk through the code.

  • Lib source file with aws runtime for having access to the ‘Context’ that is passed in to our application when it’s instantiated.

  • GHC.Generics for work with JSON

  • Aeson for (de)serializing JSON to our types

  • Handler

    • This is defined in scr/Lib
    • Must be called handler limit of Haskell runtime
    • handler :: Person -> Context -> IO (Either String Person)
  • Main

    • import aws runtime again
    • import fully qualified Lib
    • call configureLambda which will dynamically generate our dispatchers for us.
    • also of note, with compared to C++ and Rust runtimes, Haskell doesn’t need the entire runtime included with it. I am guessing it can make smart decisions about what is required
    • we can create more ‘handlers’ just need to remember to import them

BOOM

Person API *update age to a negative value or 0 and see the string response. Thanks great!

{
 "personAge": 43,
 "personName": "John Doe"
}

Picks

Resources

AWS Custom Runtimes

Runtime Details with Haskell Medium Post

Custom Haskell Runtime Repo

Lexi Lambda Guide to Haskell 2018

Follow

Published 21 Feb 2019

A show about learning Elm, Functional Programing, and generally leveling up as a JS developer.
JavaScript To Elm on Twitter