Skip to the content.


HsLua provides bindings, wrappers, types, and helper functions to bridge Haskell and Lua.


HsLua provides the glue to use Lua with Haskell, and the other way around. It provides foreign function interface (FFI) bindings, helper functions, and as well as many utilities.

Lua is a small, well-designed, embeddable scripting language. It has become the de-facto default when making programs extensible, and it is widely used everywhere from servers over games and desktop applications up to security software and embedded devices. This package provides Haskell bindings to Lua, enabling Haskell developers to embed the language into their programs, to make them scriptable, and to expose relevant Haskell code to Lua.

HsLua ships with batteries included and includes a recent Lua version, currently Lua 5.4.4. Cabal flags make it easy to compile against a system-wide Lua installation.


You should give HsLua a try if you

HsLua exposes most of Lua’s C API via Haskell functions. It offers improved type-safety when compared to the raw C functions, while also translating Lua errors to Haskell exceptions. Furthermore, HsLua provides convenience functions and helpers that make interacting with Lua straight-forward and safe.


Possibly the best-known real world use case of HsLua is pandoc, the universal document converter, where it serves as a central building block for Lua filters and custom writers.

Santa’s little Lua scripts, originally written for Advent of Haskell, is a friendly introduction that showcases how an Haskell application can be extended through Lua.


Expose a Haskell function to Lua and call it from Lua.

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}
import Control.Monad (void)
import Data.Version (makeVersion)
import HsLua
import Prelude

-- | Factorial function.
factorial :: DocumentedFunction e
factorial = defun "factorial"
  ### liftPure (\n -> product [1..n] :: Prelude.Integer)
  --                 get arg      type of arg      name  description
  <#> parameter      peekIntegral "integer"        "n"   "input number"
  =#> functionResult pushIntegral "integer|string"       "factorial of n"
  #? "Computes the factorial of an integer."
  `since` makeVersion [1,0,0]

main :: IO ()
main = run @HsLua.Exception $ do
  pushDocumentedFunction factorial *> setglobal "factorial"
  -- run a script
  void . dostring $ mconcat
    [ "print(' 5! =', factorial(5), type(factorial(5)))\n"
    , "print('30! =', factorial(30), type(factorial(30)))\n"

Running this program yields

 5! =   120     number
30! =   265252859812191058636308480000000       string

Note that the second result is too large for a Lua 64 bit integer, so the value is represented as a string.

Generated documentation

The documentation can be rendered as pandoc Markdown:

### factorial (n)

Calculates the factorial of a positive integer.

*Since: 1.0.0*


:   number for which the factorial is computed (integer)


 - product of all integers from 1 upto n (integer)


Requirements differ, HsLua is divided into multiple packages. Three types of packages are bundled in this repository. Base packages, packages for testing, and module packages.

Base packages offer an increasing level of abstraction, from raw bindings to the C API up to self-documenting, object-oriented functions, types, and modules. Testing packages provide helpers to test Haskell and Lua code, and the module packages each contain a ready-made module to be used in an application.

Base packages

Below are the base packages that provide the main functionality of HsLua. Each module depends on the ones above it.

Testing packages

Module packages

These packages each contain a documented module that can be registered in Lua.


HsLua was the topic of a talk presented at BOBKonf 2022 (Slides).