Skip to content

Connecting Haskell FRP to the Unity3D game framework – part 1


This post describes how to connect Haskell to Unity3D by compiling a Haskell shared library to a Win32 DLL and dynamically loading the DLL in a scripted Unity3D object via DLLImport. The DLL also uses an additional module (Yampa), thus FRP can be used within a sophisticated game framework (with the exception that this concept doesn’t connecte to the Unity3D core yet, which would allow stateful arrows within the game logic… which renders it rather useless right now :/).

Unity3D was chosen because it provides a complete game creation workflow and a demo version is available for free. In contrast, there are no full game creation frameworks available for Haskell right now (to my knowledge, but my status is based on ). DLLs were chosen over .NET libraries because to my knowledge it is not (yet) possible in Haskell to compile to a .NET library (and I think it was one of the reasons why F# was born). .NET libraries would of course allow for an easier integration in Unity3D. Unity plugins are only available in the pro version… which is a pity.

My personal goal was to connect functional temporal programming (functional reactive programming) to a sophisticated game framework to allow the creation of great games with FRP game logic. Besides, it was a great exercise for foreign function interfaces (FFI) and a test on how well Haskell can be integrated into existing applications.


What actually happens when a Haskell program is packed into a shared library and called from an external program?
The actual DLL is built from C code, which exports the Haskell functions and also starts up a Haskell runtime, which delegates the external function calls to Haskell. All functions are called within an unsafe environment, like main :: IO () (… this shouldn’t necessarily be the case I think – FFI to Miranda?)

  1. Install at least GHC 7, because Windows DLLs don’t work with GHC 6 (see: GHC 7 change-log, section 1.5.4. DLLs: “Shared libraries are once again supported on Windows.”).
  2. Download and install Unity3D.
  3. Download DllTest.hs (Haskell code for game logic) and adopt to your needs.
    • As these function get evaluated within a unsafe environment, they are all IO Monads.
    • In Windows you have to use ccall (citation needed)
  4. Download DllTest.cs (Unity3D script file) and adopt to your needs.
    • Make sure to start and stop the Haskell runtime correctly. Nothing special really, just tag the external functions with [DllImport] and call.
  5. Visit GHC manual and search for // StartEnd.c and save the code to StartEnd.c.
    • This is the actual C program which is converted to a Windows DLL. It also starts up a Haskell runtime and allows the external program to call functions.
  6. Install all dependent modules with shared library option enabled (f.e. yampa) $ cabal install --reinstall --enable-shared yampa.
  7. Copy shared libraries of all used modules to your Haskell project directory C:\Program Files (x86)\Haskell Platform\2011.2.0.0\lib\yampa...\libHSYampa- (…there may be a better solution for this)
  8. Copy the file C:\Program Files (x86)\Internet Explorer\IEShims.dll to your Haskell project directory (… forgot why)
  9. Compile step 1 $ ghc -dynamic -fPIC -c DllTest.hs
    • This is an intermediate step (see Shared libraries that export a C API) which produces the object file (.o) from C code (DllTest.o and DllTest_stub.o)
    • The -fPIC flag is required for all code that will end up in a shared library.
  10. Compile step 2 $ ghc -dynamic -shared DllTest.o DllTest_stub.o StartEnd.o libHSYampa- -o libHsDllTest.dll
    • The object files, the runtime starter and the archive file for the additional module are compiled together into the final DLL.
  11. Use the DependencyWalker tool of the Visual Studio IDE to find errors in the DLL (it may be included in Visual Studio Express which is available for free).
  12. Create a Unity3D project and add an object using the DllTest.cs as a script file (this is out-of-scope of this article).

Notes on Haskell DLLs

Notes on Unity3D

  • When the DLL file is recompiled, Unity3D has to be restartet in order to reload the DLL.
  • If Unity3D doesn’t find the DLL file, make sure the correct DLL file (in the directory where $ ghc is executed) is located in your Unity3D project where the .exe file is located which gets compiled by Unity3D.
  • Unity3D log files are located in: C:\Users\myuser\AppData\Local\Unity.
  • Unity3D crash reports are located in: C:\Users\gerold\AppData\Local\Temp\crash_....
  • stdcall instead of ccall on Windows, this appears to be invalid for Unity3D (also see GHC manual on Win32 DLLs.
  • Unity3D uses the following script languages: C#, JavaScript, Boo.


The actual concept is pretty straight forward. Simply write all Haskell functions and make the function interfacing to the external program an IO monad, which gets called by a potentially inpure program. The program and all depending modules are compiled into one big DLL. This DLL gets imported by the external program (Unity3D) and makes the functions visible. Before an Haskell function can be called, a complete Haskell runtime environment has to be started. In the following example, when an object is created, it starts up a Haskell runtime, runs an embedded arrow and shuts the Haskell runtime down again. This is of course rather useless right now, but it shows an arrow running in Unity3D.

DllTest.hs (short)

{-# LANGUAGE ForeignFunctionInterface, Arrows #-}

module Adder (
) where

import FRP.Yampa

embeddedSF :: Double -> Double -> Double -> IO Double
embeddedSF v0 v1 v2 = return . last $ embed integral (v0, [(1.0, Just v1), (1.0, Just v2)])

foreign export ccall embeddedSF :: Double -> Double -> Double -> IO Double

DllTest.cs (short)

class DLLTest : MonoBehaviour {
[DllImport ("libHSDllTest")]
private static extern void HsStart();
[DllImport ("libHSDLLTest")]
private static extern void HsEnd();
[DllImport ("libHSDLLTest")]
private static extern double embeddedSF(double v0, double v1, double v2);

void Awake () {
print ("embeddedSF: " + embeddedSF(12.0, 23.0, 45.0));

DllTest.cs (short)

class DLLTest : MonoBehaviour {
[DllImport ("libHSDllTest")]
private static extern void HsStart();
[DllImport ("libHSDLLTest")]
private static extern void HsEnd();
[DllImport ("libHSDLLTest")]
private static extern double embeddedSF(double v0, double v1, double v2);

void Awake () {
print ("embeddedSF: " + embeddedSF(12.0, 23.0, 45.0));


Haskell DLLs


Open questions

I don’t know how to integrate stateful arrows into the game logic yet. Probably the Haskell runtime within the DLL has to be started on some OnGameStart-event. Each object has to run its own independent arrow code and the update ticks propagated to something like the reactimate procedure.

(This post took ~4h to write, excluding development and writing the protocol, +1h update)

Tagged with , , , .

6 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Nick Wiggill says

    This is fantastic, Gerold. I’ve just found out about FRP while attempting to write a language-agnostic MVC framework for games in an OO language. I find static OO (AS3, Java, C#) very restrictive to the sort of object composition I want for entities, and dynamic prototypal OO (JS, AS2) is a step up but has shortcomings that still annoy me. True functional languages look like the answer and FRP on top of that looks even better. Re Unity, IMO you couldn’t have chosen better things to tie together than Haskell/FRP + the world’s most cross-platform game engine. Nice.

    What are your thoughts on MVC for games? Does it fit at all with your way of thinking?

  2. league of angels league of angels league of angels says

    Undeniably imagine that that you said. Your favourite reason seemed to
    be at the internet the easiest factor to take into account of.
    I say to you, I certainly get irked at the same time as people consider worries that they just don’t realize about.

    You controlled to hit the nail upon the top and defined out the whole thing with no need side effect ,
    folks can take a signal. Will likely be back to get more.

  3. says

    Appreciaate the recommendation. Let me try it out.

  4. says

    When someone writes an piece of writing he/she keeps the
    plan of a user in his/her mind that how a user can know it.
    Thus that’s why this post iis outstdanding. Thanks!

  5. for c# says

    With havin so much content do you ever run into any problems of
    plagorism or copyright violation? My website has a lot of exclusive content I’ve either authored myself or outsourced but it
    seems a lot of it is popping it up all over the web
    without my permission. Do you know any methods to help protect against content
    from being stolen? I’d certainly appreciate it.

  6. Meir Ezra says

    Well, I very first started aiding taking companies go general
    public close to 1987. Shrink typically takes various forms, but listed below are
    the four most standard. The material which u required could be learn for your certain place
    and may be shop in exact same spot again.

Some HTML is OK

or, reply to this post via trackback.