Friday, March 30, 2007

A Haskell GUI in Flex

In an earlier post I mentioned a little Haskell game I developed where you had to navigate in a maze. I used HGL as the GUI framework, and noted it wasn't very clear what was the functional GUI framework of choice for Haskell. So I decided to give Flex a go and to hook it up with my Haskell back-end. I'm quite please with the result, I have to say.
The setup is as follows:
1) I've implemented a very simple single-threaded HTTP server in Haskell, using as an inspiration code that I found here and there (using Parsec for parsing HTTP messages, etc.). The server can server static HTML and SWF files as well as having a dynamic component: you can register Haskell methods that take a JSON object as a parameter, some internal state and return a new JSON object and the new state (yes I know, there is a monad for that...). I used the code here for JSON in Haskell. I thus expose a method that generates a Maze and a method to move to a cell, validating that there is no wall in between the current cell and the target cell and checking to see if we reached the exit.
2) I use Flex and ActionScript to create the GUI. The compiled SWF file will be served by the Haskell server and will call it back through asynchronous calls. I was a bit taken aback when I realized that Flex doesn't come with JSON support out of the box, but luckily there's a library for it. So you connect via your browser to a page on the server that embeds the SWF, Flex ask for the maze data to the server and displays it, and let you navigate using the keyboards or the mouse.
And that's it! So I have a nice, platform independent GUI and functional business code. I was thinking, who needs a special GUI framework for the desktop when an application could be made easily with a very lightweight local HTTP server and a web based interface? I even thought that Flex was a bit too much: why do I need a GUI technology that requires compilation when I can do nice stuff with pure HTML/Javascript frameworks like Dojo? So I can use a UI technology that is purely for UIs, and a functional language with the goodies Haskell provide for all the back-end, computation-heavy work.
The code for Haskell is here (start from Framework.hs), the Flex code is here.

9 comments:

Anonymous said...

This is the most pragmatic approach! I am very surprised! I hope other people have this in mind.

Curious Bystander said...

I have a similar problem, so downloaded the files individually ... (An archive would have been handy), but I am still had to fight the Flash Security Model.

I have created a web-root directory I have copied in it a crossdomain.xml file with the right permisions and the shape.swf file. And I am loading the shape.swf file like this:

flashplayer http://localhost:9000/shape.swf

I am missing something "bloody" obvious?

JP Moresmau said...

Vasile, have you tried in a browser instead of the flashplayer?

Anonymous said...

Hey there

came across this blog

thanx for sharing such useful information... I thing that many people will like it

Regards
Iksanika

Jeff said...

Looks like links are dead...?

Also you use Data.ByteString unpackList function in HTTPServer.hs. I don't see that. I've found a few arcane articles about this function, but would you mind discussing it more?

Anonymous said...

links are dead. please add

JP Moresmau said...

Fixed links. Sorry. Er, for unpackList, I don't really know, it's just transforming the ByteString into a list of Word8 and I just convert that to a String holding the actual value...

Jeff said...

Just FYI - I used some of your ideas to make a JSON based web app framework that is also heavily influenced by Shellac. Just wondering if you had a chance to check it out. http://jaxclipse.com/news/node/9

So instead of passing the state around, it is in a custom monad, Srv. In the actual app you can sequence actions and do all the kinds of stuff like in a Shellac-based application. The Srv monad just stacks a StateT and ReaderT over IO. There are some utility methods, but the single threaded http processing loop is from your work here.

I would love to work this out as a multithreaded version, but still researching how to do that.

Enjoy - and please let me know if you have any comments. jeffery.caldwell@gmail.com

Anonymous said...

Instead of unpackList, you should now use unpack.