Friday, September 17, 2010

Digit recognition with a neural network. First attempt!

I bought myself "On Intelligence", and I thought as the first step on the long road to building an intelligent machine I would go back to neural networks. I have my own little library that seems to work (kind of), so I decided I was going to try to write a little number recognition program. I was inspired of course by ai-junkie, but it was a bit short on details...
So here is the problem: I have a 5x5 grid of LEDs that can be on or off, and I want to recognize the digit that they show. 
The input will be a list of 25 numbers, either 0 (off) or 1 (on)
The output will be a list of 10 numbers, either 0 or 1. The first position of a 1 indicates the result (so if the first element is a 1, it's number 0, etc).
I arbitrarily decide to set the number of hidden neurons to 50, twice the input neurons. So my topology is 25-50-10. 
I train the network with only one version of each digit. For example 3 would be:
*****
    *
 ****
    *
*****
Wrote a few lines of Haskell code to read the training sets (moving from the representation with *, spaces and new lines to the list of 1 and 0, so that 3 becomes: [1.0,1.0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0]).
Then I train the network. It learns after 200 iterations, and successfully recognizes the training sets (ok, so things are working as they should be).
Then the real test: can my network recognize small variants of the training set?
Lets's try with:
****
    *
 ***
    *
****
(a slightly rounded 3): the network answers 3!!
Works also for a slightly rounded 6. But then:
 ***
*   *
 ***
*   *
 ***
(rounded 8) gives me 6. Oh dear... I could probably add more cases in the training sets and hopefully resolve the ambiguities, but there are bigger issues (I know I know, I'm very candid, but it's one thing being told something in a book, and another to build something to actually show it to you). For example:
***
* *
***
Is a small zero that doesn't take the full 5 LED width. My network recognizes 0 when it fills the full square, not when it's smaller (tells me it's a 5).
And of course, 1 is a disaster. The training "1" is a vertical row of LEDs on the left. A vertical row of LEDs on the right gives me 9, usually (and I suppose, 9 has all the LEDs on the right on).
So not only is basic training not sufficient to detect simple variations, but also the fact that we deal with absolute positioning of leds mean than scaling and simple side translations are not supported. So I suppose the next step is to not work with absolute positions, but relative positions of "on" LEDs. Another day's work...

Monday, September 06, 2010

EclipseFP development: using the GHC Lexer

The new version of EclipseFP is slowly coming along. Slowly, because of some holidays, because of a lot of bug fixes, and mainly because of some big changes.
There were a few bugs revolving around syntax highlighting. The original code was using some lexing rules from the JFace packages in Eclipse, but it didn't cover some common enough cases of Haskell syntax, and of course was fairly hopeless at more complex stuff (things like Template Haskell). So I could either trod on and fix the lexing rules for everything, or I could use a different approach. So I decided to use Scion again, and to add support for lexing. Now Scion exposes a method that calls the GHC Lexer on an arbitrary Haskell source. We use the result to color highlight properly the Haskell source code. Of course I have to handle things like CPP preprocessing directives and literal source files myself, but that was ok. The two main issues I had to tackle were performance, and advanced lexing options.
Performance was poor at start, and there are two reasons: the underlying Scion code deals with JSON Strings while the socket code uses ByteStrings, and, I think, the Eclipse console. For the first issue, I'm using now AttoJson, so that Json marshalling is done with ByteStrings and try to use ByteString as much as possible in the code. The Eclipse console is a different matter. I think when too much data is written to it it struggles to update the console control, blocks the UI thread and the whole UI becomes unresponsive. For the moment, I have disabled server output in the console for commands (since now getting the tokens from the source code is quite a big response). Since lexing is also done in the UI thread, we've probably lost a bit in that area, but I feel the advantages (less Haskell knowledge in the Java code, more reliance on the GHC code, which I suspect knows about Haskell pretty well) outweigh the costs.
One funny thing with the Lexer I found: for example when you have TemplateHaskell code in your source file, and you have the TemplateHaskell pragma, the Lexer doesn't automatically set the TemplateHaskell flag. So I decided that I was going to enable all the lexer flags, since performance didn't seem to suffer. Be liberal in what you parse...


Anyway, I'm not going to release the next version right now, a bit of testing is still needed, and there are a few little things that I want to fix. The testing is easy, in a way: I use the development version of EclipseFP to hack the Scion code, so by eating my own dog food I hope that I can release something of value to Haskell programmers.
So don't worry, EclipseFP is coming soon!

Wednesday, June 02, 2010

EclipseFP 1.111 released

I have just released version 1.111 of EclipseFP. You can get it from sourceforge or via the Eclipse update site (http://eclipsefp.sourceforge.net/updates/).
This is mostly a bug-fixing release to ensure compatibility with GHC 6.12.1 (Haskell Platform 2010) and IPv6. It also bundles a version of the Scion source code that it builds under the covers to save people from downloading the source code from github and building it themselves.


There aren't too many feature enhancements because I didn't get any requests for it. I'm not too sure a lot of people are using EclipseFP and are interested in seeing it improved. I suppose now with a Cabalized gtk2hs Leksah becomes more attractive. Anyway, if you have requests for EclipseFP let me know!

Friday, May 28, 2010

Gtk2hs and Leksah on Windows, check!

Things have moved since I posted about the difficulty of being a Haskell programmer on Windows. Now, Gtk2hs has been cabalized and put on Hackage. I went into my MSYS prompt, and it installed like a charm! I've downloaded the latest version of Leksah, and it installed and started properly! As I write this I've seen the initial Leksah screen, and it's now busy referencing my packages (I wonder if giving it the location where Cabal stores the packages it downloads was a good idea, it seem to be taking a while...). 
So I think now all the things I was struggling to get working are now installed and doing fine on my Windows 7 machine! There is hope!

Wednesday, May 05, 2010

Haskell SDL on Windows, check! (hacking required)

Things looked grim. Even though Timothy could get it to work, the SDL Haskell library wouldn't build for me. libSDL itself installed ok and the samples compiled and ran. But I couldn't compile the hsc files because of a linker error: gcc couldn't find SDLMain or whatever. In desperation, I posted to Haskell-cafe. I didn't get a single answer or hint. I was truly alone.
OK, it was time to either give up or take drastic action. And I never give up.

By then I had narrowed the problem. The order of arguments to gcc were wrong for linking, according to the gcc manual: the .o file should be referenced before the SDL libraries on the command line. It would work like that for other people, but for me, on my system, in my corner of the universe, the order was wrong, and that was it. If I tried the same order of arguments on the SDL samples, they would fail to link. If I reverted the arguments, they would succeed.
So I was left with the straight and narrow: I managed to get the source code for hsc2hs from darcs. I fiddled for a while with the include-dirs and extra-lib options so I could get it to compile and produce the same error than I had with the Haskell Platform version, and not some stupid errors about hsFFI.h not found or so.

Then I opened up, hands trembling and sweat pouring from my forehead, Main.hs in an editor. Found the offending lines:
    rawSystemL ("linking " ++ oProgName) beVerbose linker
( [f | LinkFlag f <- flags]
++ [oProgName]
++ ["-o", progName]
)

Changed them to:

      rawSystemL ("linking " ++ oProgName) beVerbose linker
( [oProgName]
++ [f | LinkFlag f <- flags]
++ ["-o", progName]
)
So that the name of the o file would be before the libraries.
Recompiled, copied the exe in the Haskell Platform bin folder...
Relaunched the SDL build...
And watched SDL build and install properly!
Gaped at the first sample of Timothy opening up a blank window that would close when I press a key! (OK, the last print fails, but by now little errors are not going to disturb my feeling of invulnerability).
Danced around my desk!
Had a beer!

Friday, April 30, 2010

Happstack on Window, check! (in a long, round-about, fear-inducing way)

The other day I noted that I couldn't install the darcs version of Happstack on my windows machine. There was a build failure that was reported on the mailing list. So I waited a few days, and tried again. But then, before I started building Happstack, something happened. I don't exactly remember what, I think I was a bit to eager with cabal upgrade, and I upgraded some base packages that I shouldn't have. I remember directory-1.0.1.1 failing to build and having to go through MSYS to get it to build. Then more and more things needed to be upgraded and ghc-pkg check was reporting more and more weird things. When I thought I had upgraded everything, I tried happstack. happstack-util built, but then happstack-data reported that happstack-util couldn't be built because it required both time-1.1.4 and time-2-something. Oh oh. I screwed around for a while. Then I saw some posts on the web talking about removing package.conf.d. In my random experiments with cabal upgrade I had managed to install everything in my user profile and not inside my Haskell Platform directory, so there was hope!
I deleted package.conf.d. ghc-pkg list reported a saner list of packages. I tried building happstack again. Then something "funny" happened: every cabal build I was trying to do first tried to reinstall process-1.0.1.2, and failed every time!! And of course process-1.0.1.2 appeared in the ouput of ghc-pkg list... WTF? Ah, ok, directory-1.0.1.1 is still installed, let's kill the beast! And then everything worked! Happstack built, happstack "hello world" server even runs, life is happy again!
I didn't try to investigate why Cabal or directory-1.0.1.1 were insisting on reinstalling something that I have already. I've seen enough weird things and spent enough time this week away from the nice world of pure lazy functional programming and in dirty low-level configuration and build issues to not care too much anymore...

Wednesday, April 28, 2010

WXWidgets and WxHaskell on Windows, check!

Despite my earlier problems, I finally managed to install WXWidgets and WxHaskell on my Windows machine. Pfiu! I started again from scratch, and things went much better when I installed, as recommended, MinGW and MSYS in different folders. When I need to compile stuff, I only put MinGW in my path, and when I need Unixy tools like make I add MSYS. Of course MinGW has its own version of make, mingw32-make, that works when MSYS make doesn't...

So I installed MinGW in c:\dev\MinGW and:
set PATH=c:\dev\MinGW\bin;c:\dev\MinGW\libexec\gcc\mingw32\3.4.5;%PATH%

Then I modified the WxWidgets config.gcc file to set SHARED=1 UNICODE=1 MONOLITHIC=1.
And then:
mingw32-make -f makefile.gcc BUILD=debug
worked!

Setting new environment variables (wxWidgets is installed in c:\ui):
set WXWIN=c:\ui\wxWidgets-2.8.10
set WXCFG=gcc_dll\mswud

Then I could install then wxdirect, wxcore and wx packages using a few more flags than what a default cabal install would do, for example:
runhaskell Setup configure --extra-lib-dirs=c:\dev\MinGW\lib --extra-include-dirs=c:\dev\MinGW\include --extra-include-dirs=c:\dev\MinGW\include\c++\3.4.5\mingw32 --extra-include-dirs=c:\ui\wxWidgets-2.8.10\include --extra-include-dirs=c:\dev\MinGW\include\c++\3.4.5

And it install, and works!

Thursday, April 22, 2010

The sorry plight of a Windows programmer (aka me)

Having secured fame and fortune with MazesOfMonad, my console based RPG, and having some ideas for some games that would look even better with a graphical front end, I decided it was time to take the bulls by the horn and go seriously into Haskell GUI programming. Well, the bull won and I feel truly gored...
So what's wrong? Well, after fooling around on my Windows 7 computer for a few nights I've achieved nothing. I now have three different copies of MinGW installed in different places. I have tried to installed SDL, GTK2HS, WXWidgets and Happstack and I have failed at all of them. I know WXWidgets is manageable because I've done it before, I only seem to have some include paths issues. libSDL itself installed but not the Haskell bindings. I found somebody with the same problem on the web, that then told me he had given up. I even managed to get Darcs errors with Gtk2Hs. In despair I thought I could develop a web based game but even the darcs version of happstack failed to compile, I remembered then some bug mentioned on the mailing list, so I should probably just download the latest stable version instead of the development branch.
Some problems are down to some silly things I did. For example installing the Haskell Platform in a directory with spaces is not a great idea (I don't remember if it was the default), because then a lot of paths referencing its MinGW install are wrong in the MSYS shell...
But most are due to the Unixy nature of a lot of the GUI components. Now I see a configure script and my blood freezes. I run "cabal install foo" and I get the dreaded message "this package has a configure script, you need to dive into Unix hell". Can you tell me why I have three versions of GCC, and two make a configure script crash with "c compiler cannot create executables" and the third one works? Where can I download one single file that will allow me to have a full MSYS/MinGW setup with most of what I need? I'm sure there are solutions to a lot of the problems I have, and maybe I need to spend more time reading the INSTALL files and such, and download everything from the MinGW files page. But why can't it Just Work? I mean, I work with Java at work, we do GUI work in SWT now and before that in Swing, we use a lot of libraries, and we never run into any installation problem. Maybe once or twice over the past couple of years we had a cross-platform compatibility issue or a library conflict. I know, I know, apples and oranges, but I'm now thinking that writing my own lazy, purely functional language with monads on top of the JVM with Java integration is going to be easier than getting a GUI library with Haskell bindings to work.
I like to write applications, not spend my free time trying to get libraries to install.

Friday, April 09, 2010

Found my neural network bug (three years later)

After the university of Waterloo AI Challenge I went back to a bit of AI programming in Haskell. Three years ago I had written some code to implement a neural network, and it didn't seem to learn as fast as the book said it should. I had not worked on that any more, but I decided to look at it again. And I found a bug!! I mixed up the deltas to pass on from one run to the next. Changing two lines of code makes my network learning much faster.
So now onto something a bit more meaty than exclusive or: very simple character recognition. I want to be able to recognize numbers written as a digital alarm clock would display them (at least mine): you have 7 lights, four vertical and three horizontal, and various patterns make the numbers. If all lights are on, it's 8, if only the middle horizontal light is off we have zero, etc...
I just test things with a network that has 7 input neurons (one for each light), 10 output neurons (one for each number) and 8 hidden neurons (the average between input and output)

g<-getStdGen
n<-network 7 8 10
let trainingSet=[
([1,1,1,-1,1,1,1],[1,0,0,0,0,0,0,0,0,0]), -- 0
([-1,-1,1,-1,-1,1,-1],[0,1,0,0,0,0,0,0,0,0]), -- 1
([1,-1,1,1,1,-1,1],[0,0,1,0,0,0,0,0,0,0]), -- 2
([1,-1,1,1,-1,1,1],[0,0,0,1,0,0,0,0,0,0]), -- 3
([-1,1,1,1,-1,1,-1],[0,0,0,0,1,0,0,0,0,0]), -- 4
([1,1,-1,1,-1,1,1],[0,0,0,0,0,1,0,0,0,0]), -- 5
([1,1,-1,1,1,1,1],[0,0,0,0,0,0,1,0,0,0]), -- 6
([1,1,1,-1,-1,1,-1],[0,0,0,0,0,0,0,1,0,0]), -- 7
([1,1,1,1,1,1,1],[0,0,0,0,0,0,0,0,1,0]), -- 8
([1,1,1,1,-1,1,1],[0,0,0,0,0,0,0,0,0,1]) -- 9
]
let (LNS(n',err,ds),e) = run (initialState n) defaultLearningRate trainingSet (1,1000)

And after something like 150 iterations I get a network that has a low error rate. A little helper method to massage the results:

runNumber n inputs=do
let
(_, output)=exec n inputs
normalized=map (\v->if (1-v)>0.5 then 0 else 1) output
return $ elemIndex 1 normalized

Et voila!

Main> runNumber nn [1,-1,1,1,-1,1,1]
Just 3

Now, things are starting to get interesting! Hopefully I won't wait another three years before trying maybe more complex character recognition.

Thursday, February 11, 2010

Waterloo Contest and Human Intelligence

I've entered the Waterloo university Google AI Challenge, hiding under a cunning nickname, since I saw that you could develop in Haskell, and a few others Haskellers are on it too! At the moment, I'm cruising at around the 110th position, which is not too bad given that I only worked a few hours at night on it (I have a day job, you know...) and that I implemented everything myself since the starter pack wasn't ready when I started working. I've played a bit with the standard strategies, implemented some flood fill, reuse some A* implementation I have.
All of this is interesting, of course, but there is no AI as such. The only intelligence in my code is the one I put in, and the strategies I devised. So I'm thinking of playing around with genetic programming and evolution techniques to try to get my code to find the right strategies at the right time. I have the feeling the trick will be to design something that is not too restricted and is truly able to evolve into some more advanced and complex than what I've designed myself. But hey, I'll learn, even if my program doesn't (-:

Monday, February 01, 2010

EclipseFP 1.110 released, with debugging support

Hello,
I have released a new version of EclipseFP. OK, I haven't kept to the one-release-a-month schedule, but with the Christmas season and everything, I deserved a break.
I have fixed a few issues here and there (thanks for everybody who commented on the blog or used the Sourceforge tracker or forum), and tried to externalize strings into resources, but there's still a lot to be done on that subject.
I have mainly worked at integrating the GHCi debugger with the Eclipse debugging framework. This tutorial was really useful! Now what works is that you can set breakpoints in the source, and GHCi will stop at them if launched in debug mode in Eclipse. Once stopped (either via a breakpoint or if you use :step) you can see the bindings and force their evaluation (use the set value to variable function in Eclipse). You can also create some expressions and get them evaluated. Underneath with use GHCi commands like :show bindings, etc.
I have removed some obsolete preferences and added debugging preferences (stop on error/exception, use show instances...).
I'll be happy with any feedback on all these features. One thing missing is support for :hist when invoking :trace, tell me if you'd like that.
Enjoy!

Monday, November 23, 2009

EclipseFP 1.109.0 is out!

A month exactly after the previous release, I got another release of EclipseFP out! I tried to fix some of the issues that people reported, to improve the overall stability of the plugins and incorporated some new features that I hope could be useful (generation of extensions and ghc-options field in Cabal from the preferences, some quick fixes on GHC warnings...). I'll need feedback from users to know what features are really needed and could make a different to Haskell hackers.

On a related note, I read that in "Coders at Work" Simon Peyton-Jones talks about the need for Visual Studio and Eclipse based IDEs to get more people interested in functional languages. I hope that my modest contribution helps...

Friday, October 23, 2009

Releasing my code on the unsuspecting public (EclipseFP)

Today I've released a new version of EclipseFP (Haskell support in Eclipse). There are quite a few changes in it, and there are even some changes in the Scion library that I've made and that Nominolo integrated. So people can give it a try if they want: get the current Scion source code, build/install it, and get the 1.108 version of EclipseFP.
Hopefully that's another step for me in getting more proficient in Haskell: interacting with other Haskell hackers, learning from them and their code, and releasing code that may actually been of use to somebody (or annoy them no end if it doesn't work) instead of only a little game as before. And of course working on an Haskell IDE, even in Java, gets me to learn new things about the language, the options for Cabal or GHC, etc...
Anyway, I hope I'll get some feedback on the new EclipseFP, and that we can move that thing forward!

Friday, October 09, 2009

What client for an Haskell Multi Player Game?

I've been thinking again, in between working on eclipsefp, about writing a multi player role-playing game in Haskell. OK, I'm not going to write something the size of WoW by myself in my free time (unfortunately my day job doesn't involve any game programming nor any Haskell hacking :-(), but since I enjoyed writing Mazes of Monad, I figured that a game is a good way to learn things. A MMORPG should get me into concurrency, persistence, graphics, performance etc...

What I'm trying to figure out at the moment is what architecture to use. Mainly, if I have no doubt there is going to be a server somewhere running Haskell code, I wonder about the client. Should I try to write a browser based game coupled with a Haskell web server? That way, users could easily play the game when (if) it gets to a usable state, and I won't have to worry about cross platform issues for the client. Getting proper server side events or push should be fun, and of course if I end up using something like web sockets I will probably require a fairly cutting edge browser, which negates the advantage. I'm not too sure meddling with AJAX long polling and dynamic HTML is such a attractive option.
The other path is to write a Haskell client. Granted, users will have to download it, which means either me dealing with cross platform issues (provide several exes) or restricting my users to people happy to use cabal install. But I'll get maybe into stuff like OpenGL in Haskell, and do everything in Haskell instead of mixing Haskell with HTML and JavaScript (I've just stumbled upon jmacro, which could be cool I guess).

I'm sure everybody has faced that question at some stage. Ah well, for the moment I'm still wondering what my game will do, so I guess I have time to play with a few things before I make my mind up.

Monday, September 28, 2009

Haskell development in Eclipse

I have started contributing to the eclipsefp project. For those who don't know, it's a Eclipse-based environment for developing in Haskell.
EclipseFP has had a troubled history so far. Leif started the project and developed an impressive set of features. He then pursued the Cohatoe project to be able to write Eclipse plugins inm Haskell, in a effort to avoid rewriting in Java all kind of things that already existed in Haskell. And then this summer Thomas started integrating with Scion, which is a Haskell library that communicates with JSON data over simple sockets with non Haskell clients. Scion offers method to load Cabal projects, type check files, etc... That work is not finished, but Leif and Thomas have done such a great job that it's easy enough now to finish the missing bits here and there.
This is perfect for me: part of the work is in Java and Eclipse, which is a lot of what I do in my day job, so I can bring a lot of experience there. Scion is a small enough library that need to be extended to provide me with all I want, so I can do little enhancements in Haskell and slowly build on features. And, last but not least, I need to learn the GHC API (which is what Scion uses to parse, check and compile files), to find what I need for.
This will only enhance my knowledge of Haskell, and I hope that I'll be able to make something useful to provide Haskell hackers with another IDE to develop in.
For those interested, the github repositories where my current work can be found are:

git://github.com/JPMoresmau/scion.git
git://github.com/JPMoresmau/eclipsefp.git

Friday, August 07, 2009

Yoohoo: mazes of monad is kind of popular!

Don Stewart has published some statistics on packages popularity here . MazesOfMonad is the fastest rising application over the past 4 months. Thanks to all people who downloaded it, hope you enjoyed it, feel free to send me bug reports or enhancement requests. Hopefully I'll find the free time (in between day work, family, sports, etc.) to develop another more ambitious game in the coming months!

Friday, July 10, 2009

Mazes of Monad: 1.0.5 and (maybe) final version uploaded

I've uploaded yesterday on Hackage the 1.0.5 version of my Role Playing Game called Mazes of Monad. I think this will be the last upload unless some big bugs are found. But I think I'll stop here in terms of functionality. It was fun, I learned a lot about Haskell, both on programming with the language, and on how to design Haskell code. Working on a full project over a long period of time forced me to actually understand code I had written previously and make it evolve instead of just having a clean slate.

I also realized than while developing a game is a lot of fun, the actual programming is the, ahem, easy part. I find that the actual game design (how to get usable and useful features) and the tweaking of the difficulty, for example, are the most challenging. For a while my test character was quite a strong warrior and I thought the game was easy, so I changed some settings to make it harder, then I realized that I had made it quite hard to start with a poor naked wizard that knew only one spell... I can see that balancing all the different game settings and getting the right formulas is critical, and that only comes from testing and collecting feedback...

Anyway, I have ideas for other games, probably the next one will be web based to have some kind of GUI and be multi player, maybe using happstack as the server (or should I just use a little home grown server in Haskell, for fun?). I'll keep on posting about that!

Friday, May 15, 2009

Adding a Writer Monad transformer

I'm still working on MazesOfMonad, my Haskell RPG, now on code.haskell.org. It's actually fun to now have a working program and think about extensions in functionality, and then how to implement them in Haskell, instead of just playing around with the language.
I wanted to give the user more feedback that they currently got about what was going on in the game, and at the same time I wasn't happy with what I had written previously: I had the output messages as part of the method signature:

myFunction :: Type1 -> Type2 -> (Type3,[String])

So I decided a Monad was called for. The Writer Monad, in this case, which lets us append stuff together to get it all back at the end. I already had most of my game running in a monad transformer, so it was **just** a matter of figuring out how to wrap everything in a WriterT. I had a bit of fun at first, then got it working. So now my game runs in a

WriterT a (RandT (StateT b IO)) c

Where a b a are various types for the things I need: a is the type of messages I write, b the state I keep, and c the return value. RandT gives me random numbers, StateT gives me a state, IO allows me to do IO operations when I need to save the game or something like that.

The amazing thing, well, for me, is that a lot of my functions do not need to be aware of the whole transformer stack, but of only the type classes that they care about. My final transformer is an instance of both MonadWriter and MonadRandom. So my method that needs to write messages becomes:

myFunction :: (MonadWriter [String] m)=>Type1 -> Type2 -> m Type3

And I can write my code calling the MonadWriter methods to add messages. It's in a monad, but it's still purely functional: I return a Type3 object and write Strings. If my function needs random numbers:

myFunction :: (MonadRandom m, MonadWriter [String] m)=>Type1 -> Type2 -> m Type3

and I get random numbers capabilities!

The final code is now much cleaner than before (I actually don't use [String] directly for the MonadWriter type but an alias for it, so I can replace it with Seq String or something faster the day I fancy it). I think I now understand monads and monad type classes better, and I understand better how using a monad doesn't automatically mean using the IO Monad and lose purity. Haskell Nirvana is not far off, says he naively...

Monday, April 27, 2009

Haskell RPG Game uploaded on Hackage!

I've worked on it on and off for months, I've rewritten parts of it entirely, it gave me the opportunity to knock together a real, complete application in Haskell, and it's finally done! I've uploaded my console based RPG game (read: nethack clone) to Hackage (get it here). You create a character and walk through mazes, trading, stealing, casting spells and fighting monsters.
You can look at the source code (no documentation, sorry) and see what I've used. I've used a monad to abstract away the state and the random generator (so I can plug a non random generator for testing, one that for example will guarantee that the next throw of the D20 die will give 8). I have developped my own little framework for console handling (executing actions from what the user typed in and displaying results) maybe I should look at the existing libraries and try to plug one in instead.
What I found was the most awkward was the record syntax for nested structures, I'll have to investigate to find an easier way to read and update my structures.
There are a few HUnit tests to verify that the most basic functionality works, so hopefully there is no huge bug.
It was fun to play around with Haskell and with game concepts. I hope I'll have time to work on even cooler stuff like adding AI for the monsters (so they can decide when to run away, etc...).
Any feedback on the game mechanism or on the code itself is welcome!

Friday, February 27, 2009

A high-level GUI library for Haskell

There seems to still be a void in the Haskell world regarding GUI libraries. On one hand we have low level libraries based on well know solutions but doing everything in the IO monad, to cut short, on another functional reactive libraries that just don't seem to be accessible for haskell programmers of my level, somehow... And I'm not the only one: just the other day I saw a new attempt being made at a functional easy to use GUI library: Barrie. It looks promising, but I had already started my own, so I think I'm going to continue a little bit, I find I'm learning a lot in the process...

The ideas being my own library, tentatively called UITree are the following:

- you build your GUI using combinators that start from simple widgets and use composite widgets and layouts to augment a tree
- event handler can be attached to widgets in the tree. The handlers are of type (ui, state)->IO(ui,state): you get the current ui tree and the current state, and you transform them. The IO bit is to allow you to do IO actions if you want but you can do without.

- inside the event handlers you manipulate the ui tree a bit like JQuery does with HTML DOM: you can select particular widgets, operate on them, etc... Most operations are just transformers from the UITree type to the same type, so you can chain them.

- since you can't reference directly the widgets in your fonctional tree, you can give them explicit ids, so there is a disconnect between the actual tree and the handlers, which is similar to JQuery (you cannot rely on the compiler to make sure you manipulate an existing widget).


For the moment I got some small samples to work with WXWidgets (Barrie uses GTK, by the way).
The API is bound to change, but this is how a frame containing a close button and a button that increases a internal integer state and displays the current state:



simpleState :: IO (Int)
simpleState=do
start simpleUI 0 -- start the WXWidgets UI with the given UI tree and initial state
where
simpleUI=(frame [text := "Simple"]) -- the enclosing frame
(
(panel []) -- a panel to enclose our children
(row [space := 5] -- children in a row, a bit of space
[
(button [text := "0"] [command :> (return . doInc)]), -- a button showing 0 and increasing the state when clicked
(button [wid:="close", text := "Close!"] [command :> (pureUI doClose)]) -- a button to close the frame, pureUI is just a helper function that shows we're not modifying the state
]
)
)
doInc (tree,st)=(set [text := (show (st+1))] tree,(st+1)) -- set the button text and state to state + 1
doClose tree=close $ top tree -- close the top of the tree (the frame)

Note how the ui building and the handlers are pure functions, so you just manipulate your tree and your state.

Friday, November 28, 2008

Predictable random for testing

In my Haskell RPG game, the results of actions are random: I use the standard random generator to simulate the throw of a dice in a table top RPG.
However for writing unit tests that is not ideal, since I would like to be able to test the outcome of an action for a given result of the dice. I didn't
want to clutter the code (even if using a State monad) with something used only for testing, so I experimented with IORef and a custom Test Generator.

First of all, we need a data type to store our non random random generator. It will store a list of results and the index it's at in that list. It's
basically a circular list, so that when we reach the end we start again. If the list is one element long, then the same result will be given for all
dice throws:

data TestGen = TestGen [Int] Int


mkTestGen is just a helper function to initialise the index to 0

mkTestGen l=TestGen l 0


This is the real magic: I thought you needed to pass around an IORef as any other variable to be able to read its results, but in fact this is not necessary,
if somewhat of a kludge:

testGen :: IORef (TestGen)
{-# NOINLINE testGen #-}
testGen=unsafePerformIO (newIORef (mkTestGen []))


This means that testGen is initialized only once as a TestGen with an empty list, no matter how many time it's called. It seemed to work in ghci even
without the NOINLINE pragma. Don't ask me why. So, given a simple setter function:


setTestGen l=do
writeIORef testGen (mkTestGen l)


We can specify what we want as the random generator. If we have an empty list, we use the standard random generator, otherwise we return the current element
in the list, and increment the index, going back to zero if we overrun the list:


randomInt ::(Int,Int) -> IO (Int)
randomInt (l,h)=do
(TestGen list ix)<-readIORef testGen
if null list
then getStdRandom (randomR (l,h))
else do
let e=list!!ix
let ix'=ix+1
let ix''=if ix'==(length list)
then 0
else ix'
writeIORef testGen (TestGen list ix'')
if e<l || e>h
then error (printf "%d not in range (%d,%d)" e l h)
else return e


And this works, amazingly:


setTestGen [2]
l<-replicateM 3 (randomInt (1,6))
assertEqual ("l is not 3 2s") [2,2,2] l
setTestGen [2,3,4]
l<-replicateM 4 (randomInt (1,6))
assertEqual ("l is not 2,3,4,2") [2,3,4,2] l
setTestGen []


(Notice how I reset the test generator to standard at the end by passing an empty list).

So now I can test my code with predictable results, that will be still random in production use.
Oops, already found a bug on the first test written with that technique!

Monday, November 03, 2008

Haskell for counting votes!

There's apparently an important election going on in the States. There are also a few interesting articles, for example in the french maths magazine Tangente (no up to date online edition that I could find unfortunately) and in the New Scientist, on how the way you tally votes affect the outcome. Tangente has a stiking example, and I'll go through the 5 vote couting methods they outline with an Haskell implementation of each.
No pesky elephant vs donkey, here, the election is about your favorite female movie star:

data Star = MarylinMonroe | AngelinaJolie | BrigitteBardot | EmmanuelleBeart | ClaudiaCardinale
deriving (Show,Read,Eq,Bounded,Enum,Ord,Ix)


Note the "deriving Ix" (from Data.Array.IArray) so we can use the stars as array indices.

We have six elector profiles: each profile has ranked the stars in order of preferences, and we have the numbers (in millions, say) of electors for that profile. For example, 7.2 million people prefer MarylinMonroe, then Emanuelle Beart, then Claudia Cardinale, 4.8 millions prefer Angelina Jolie, etc. Here's the full data:

votes :: [(Double,[Star])]
votes = [
(7.2,[MarylinMonroe,EmmanuelleBeart,ClaudiaCardinale,BrigitteBardot,AngelinaJolie]),
(4.8,[AngelinaJolie,ClaudiaCardinale,EmmanuelleBeart,BrigitteBardot,MarylinMonroe]),
(4,[BrigitteBardot,AngelinaJolie,ClaudiaCardinale,EmmanuelleBeart,MarylinMonroe]),
(3.6,[EmmanuelleBeart,BrigitteBardot,ClaudiaCardinale,AngelinaJolie,MarylinMonroe]),
(1.6,[ClaudiaCardinale,AngelinaJolie,EmmanuelleBeart,BrigitteBardot,MarylinMonroe]),
(0.8,[ClaudiaCardinale,BrigitteBardot,EmmanuelleBeart,AngelinaJolie,MarylinMonroe])
]


With this we need a few helper method before we're ready to implement our voting algorithms.

We need a way to tally votes for stars, taking into account that several profiles may vote for the same star at the same round (Claudia Cardinale at the first round, say). We use an array with the addition as accumulation function, sorted my popularity
accumVotes ::  [(Star,Double)] ->  [(Star,Double)]
accumVotes v=let
arr=(accumArray (+) 0 (MarylinMonroe,ClaudiaCardinale) v):: Array Star Double
in sortBy (\a b -> compare (snd b) (snd a)) (assocs arr)


For some reason I needed to tell GHC about the array type, it couldn't infer it.
We need a way to get the votes for a given round (even if we'll only be using the first round this way)
roundResults :: Int -> [(Star,Double)]
roundResults r=let
v=map (\(a,b)->(b !! r,a)) votes
in accumVotes v


And a simple extraction function to get the winner's name from accumulated votes:
bestVote ::[(Star,Double)] -> Star
bestVote v= fst $ head $ (accumVotes v)


Now we're ready. The first algorith is a simple one round voting election:

oneRound :: Star
oneRound=bestVote (roundResults 0)


This makes Marylin Monroe the clear winner. But a lot of countries use a two round system: the most popular candidates after the first round make it through to the second round:

We first need a helper function that retrieves the first element from a first list found in a second list (is there a standard method somewhere?)
findFirst :: Eq a => [a] -> [a] -> a 
findFirst toFind (a:rest) = if elem a toFind
then a
else findFirst toFind rest


Then it's straightforward: we get the first two candidates after the first round, and accumulate their results over all the profiles
twoRounds :: Star
twoRounds= let
(fr1:fr2:_)=(roundResults 0)
allScores=map (\(a,b)->(findFirst [fst fr1,fst fr2] b,a)) votes
in bestVote allScores


Angelina Jolie for President! A third method we can use is to proceed by elimination: at each round, we drop the least popular candidate, until we get only one:

elimination :: Star
elimination= fst $ elimination' (roundResults 0)
where
elimination' :: [(Star,Double)] -> (Star,Double)
elimination' (a:b:[])=a
elimination' l= let
firstRound= map fst $ init l
in elimination' $ filter (\a->(snd a) >0.0 ) $ accumVotes $ map (\(a,b)->(findFirst firstRound b,a)) votes


This little recursivity yields Brigitte Bardot. Borda suggested another method: we assign a weight to each candidate depending on its ranking, that weight is used as a multiplier of the votes. First choice gets a total tally of the votes times 5, second choice 4, etc.

borda :: Star
borda = bestVote $ concat $ map (\(a,ss)-> map (\(s,mul)->(s,mul*a)) (zip ss [5,4 .. 1])) votes


And this time, Emanuelle Béart comes on top! Last method we will survey is from Condorcet: we look at each match bewteen two stars in isolation. A match is won if more votes put the first star in front of the second star. We first calculate all the possible matches than consider each won match as 1 vote, and accumulate as before:

condorcet :: Star
condorcet= let
matches=[[x,y] | x <-allStars, y <- tail [x .. ClaudiaCardinale]]
matchResults= map (\match->(bestVote $ map (\(a,b)->(findFirst match b,a)) votes,1)) matches
in bestVote matchResults


And, behold, the winner through this method is... Claudia Cardinale! Five methods, five winners!
Of course these are really quick draft of voting methods, they should take into accound draws, etc... Do not use this code to elect the president of a real country!

Tuesday, September 02, 2008

Arrays to the rescue!

Some time ago I blogged about Haskell Generics and how they simplified my code of a little RPG game I'm writing. My data types were designed with lists. For example a character has traits, and traits are a list of Characteristic objects, that have a name (Strength, Dexterity, etc.) and values. The Generics code helped me to deal with finding the right item in the list depending on the name, updating its value, etc. Records were no good because you can pass the generated function as an accessor but not as a mutator.

I have some unit tests that generate random characters, and I thought they were pretty slow, which I thought was due to the random number generator. Then I ran the tests with profiling on. Guess what? The Generics code amounted for a huge amount of the time spent. And I'd say the underlying list operation, with loads of list updates, were not great either.

So I got rid of the Generics code, and I decided to replace my lists by something else. In the Java world (my day time job) I rely heavily on Maps. I thought it was a bit overkill in this case, so I turned to the Haskell array package. And there was light!

You see, Arrays in Haskell are a different beast that arrays in other languages. You can use different types for the indices, not only integers. So since the data type representing the names of characteristics is a simple enumeration, I could use that as the array index. So the characters traits are an array with the names as indices:

data Characteristic = Strength | Dexterity | ...
deriving (Show,Read,Eq,Enum,Bounded,Ord,Ix)

Ix is the type class that an array index type must implement

type CharacteristicRatings=Array Characteristic Rating

data Character = Character {
...
,traits::CharacteristicRatings
...
}

And Rating follow the same pattern, since a rating has the current value for the characteristic, the normal value, etc.

Then the array operations make it easy enough to read and modify values: ! to get the value at the specified index, // to update. I get type safety and expressiveness (no need to even use toEnum and fromEnum), and performance...

Performance? With the Generics code and lists, my tests took 8 seconds. With arrays and no Generics, 0.26s. Nuff said.

Friday, July 11, 2008

instance Data Map where -- half done!

While testing my JSON serializer/deserializer, I made the (unpleasant) discovery that some standard structures (most notable Data.Map.Map) do not implement all of Data.Generics.Data interface. They just call error on things like toConstr and gunfold. Which is not good, since I use these methods. Why they can't just pretend that a Map K v is for generics a map of (k,v) I don't understand (they implement gfoldl that way), but hey, I'm only a humble learner of Haskell...

So I spent a few hours trying to modify my JSON code to work around this issue, to no avail (well I can get the serialization all right, but the deserialization seems to be tricky). So I've got another approach to work: since the default for Data instances is not right when your objects contains Map structures, lets rewrite these... Using the source for Data.Map and the documentation for Data.Generics.Data, I managed to get it to work, but of course the price is loads (loads, loads) of boilerplate code.

So here goes: I have the simple object: (assume import qualified Data.Map as M)

data MapObjF=MapObjF (M.Map String Int) String
deriving (Eq,Typeable,Show)


So MapObjF contains a Map String Integer and a String

And here's the Data instance definition (big breath):


instance Data MapObjF where
gfoldl k z (MapObjF m s) = k (k (z (MapObjF . M.fromList)) (M.toList m)) s
gunfold k z _ = k (k (z (MapObjF . M.fromList)))
toConstr (MapObjF _ _) = con_MapObjF
dataTypeOf _ = ty_MapObjF

con_MapObjF = mkConstr ty_MapObjF "MapObjF" [] Prefix
ty_MapObjF = mkDataType "MyModule.MapObjF" [con_MapObjF]


I define the constructor, the datatype, and implement gfoldl and gunfold transforming the map into a list of tuples. Of course if you have several constructors, loads of fields it soon becomes unwieldy. Now, is there a Haskell macro system so I can easily generate all that boilerplate for all my data types? Noooo I don't want to leave Haskell for LISP...

Tuesday, July 08, 2008

Handling errors in JSON to Haskell deserialization

My JSON deserializing code presented previously works, but when an error occurs, most likely because the JSON doesn't represent the objects you expect it to, we're a bit lost: we get a terse error message and our program aborts, because Data.Generics tend to call error when it encounters a problem, and our own calls from Maybe to Just may fail. So we need to build a way to report errors without crashing. Now, famously, there are several ways to report errors, and for a start I'll work with Either.

First, we create a error type that can help us represent both JSON parsing error and deserialization errors:

data JSOND13NError=JSONError ParseError
| D13NError String String
deriving Show


The two parameters in D13NError are the error message and the path in the JSON object where the error occured. They will be carried in the Either monad in a tuple of Strings

So parsing can either throw a JSONError or try to deserialize:

jsonStringToObj :: forall a. Data a => String -> Either JSOND13NError a
jsonStringToObj s= case parse JSON.json "JSON.parse" s of
Left err->Left (JSONError err)
Right js->case (jsonToObj js "/") of
Left (s,path) -> Left (D13NError s path)
Right o-> Right o


The path starts at "/" for the deserialization

To work with Either we need a couple of helper function, one to translate the Maybe values we get from cast to Either:

toEither :: String -> Maybe a -> String -> Either (String,String) a
toEither s Nothing path=Left (s,path)
toEither _ (Just a) _=Right a


And then the monad declaration for Either(message,path):

instance Monad (Either (String,String)) where
return a=Right a
fail s=Left (s,"/")
Right a >>= f2 =f2 a
Left s >>= f2 =Left s


With this, our main function becomes:

jsonToObj :: forall a. Data a => JSON.Value -> String -> Either (String,String) a
jsonToObj (JSON.String s) path=toEither "Not a String" (cast s) path
jsonToObj (JSON.Bool b) path=toEither "Not a Bool" (cast b) path
jsonToObj x path=do
(values,cons)<-case x of
JSON.Object m -> fieldJSONValues m myDataType path
JSON.Number fl -> Right ([],if isPrefixOf "Prelude.Int" (dataTypeName myDataType)
then mkIntConstr myDataType (round fl)
else mkFloatConstr myDataType fl)
JSON.Array [] -> Right ([],indexConstr myDataType 1)
JSON.Array (x:xs) -> Right ([(x,path),((JSON.Array xs),path)],indexConstr myDataType 2)
let StateT f=fromConstrM (StateT (\((x,path):xs) -> do
r<-jsonToObj x path
return (r,xs)
)) cons
r<- f values
return (fst r)
where
getArg :: a' -> a'
getArg = undefined
getType :: a
getType = undefined
myDataType = dataTypeOf (getArg getType)


We use a StateT monad transformer to wrap our Either monad in the State. I'm not sure I understand 100% of how monad transformers actually work, but it works!

And the fieldJSONValues handles a few error conditions, along with building the path where we're at, by adding after the current path the name of each field in turn

fieldJSONValues :: (M.Map String JSON.Value) -> DataType -> String -> Either (String,String) ([(JSON.Value,String)],Constr)
fieldJSONValues m dt path | isAlgType dt=
if idx>(maxConstrIndex dt)
then Left ((printf "Constructor index %d too big" idx),path)
else
if null fn
then Right ((map (\x->(fromJust $ M.lookup (show x) m',path++(show x)++"/")) (sort $ map (\x->((read x)::Int)) (M.keys m'))),c)
else
let vals=map (\(x,y)->(fromJust x,y)) (filter (\(x,y)->isJust x) (map (\x->((M.lookup x m'),path++x++"/")) fn))
in if (length vals) < (length fn)
then Left ("Not enough fields",path)
else Right (vals,c)
where
idx=case M.lookup constrIndexField m of
Just (JSON.Number f)->truncate f
_ -> 1
m'=M.delete constrIndexField m
c=indexConstr dt idx
fn=constrFields c
fieldJSONValues m dt path | otherwise =Left ("Not an algebraic type",path)


Once I had the previous code working, using a different monad and adding error handling was easy. I suppose I could further abstract and try not to hard code the Either monad in it but use any type of Monad or MonadError, but this gives me what I want: no program crash and the ability to recover from errors!

Friday, June 27, 2008

Deserializing JSON to Haskell Data objects

Since last week I found a few other posts and libraries on the subject of JSON serialization and deserialization: here and here for example. Nonetheless I've continued on my own path, since the best way of learning is doing. It took me a while to figure out how to reconstruct a Haskell object, and I've only got some limited functionnality to work, but it works. I looked into the source code for gread for clues, I have to say.

So what we want is simple enough:

jsonToObj :: forall a. Data a => JSON.Value -> a


Given a JSON value we want an haskell object, and hopefully the type will match... OK, I'm a bit terse on the error handling side of things at the moment!
(Note: for the code to work you need to import: Control.Monad.State, Data.Generics, Data.List, qualified Data.Map as M, Data.Maybe)

It's simple enough for Strings and Bools:

jsonToObj (JSON.String s)=fromJust $ cast s
jsonToObj (JSON.Bool b)=fromJust $ cast b


Of course, if you expected a Foo and parse a JSON.String, this will fail(The cast return a Maybe). You have to cast since the signature doesn't force Strings or Bools, only Data.

For other types of objects (including numbers, because cast doesn't perform number conversion I found) it's a bit more complicated. Basically we have to figure out the type we want, find a constructor to build an instance of that type, and pass to that constructors proper values from the JSON object.
To find the type we want, I use funny code find in gread:

myDataType = dataTypeOf (getArg getType)
getArg :: a' -> a'
getArg = undefined
getType :: a
getType = undefined


This create a dummy function returning my type, and a dummy function returning what it gets as parameter. They don't need to be implemented, the compiler only cares about the type.

The meat of the function, that decides what constructor to invoke and what data to useas constructor parameter is a bit more involved:
(values,cons)=case x of
JSON.Object m -> let
c=indexConstr myDataType 1
in ((map (\x->fromJust $ M.lookup x m) (constrFields c)),c)
JSON.Number fl -> ([],if isPrefixOf "Prelude.Int" (dataTypeName myDataType)
then mkIntConstr myDataType (round fl)
else mkFloatConstr myDataType fl)
JSON.Array [] -> ([],indexConstr myDataType 1)
JSON.Array (x:xs) -> ([x,(JSON.Array xs)],indexConstr myDataType 2)


This snippet calculates the objects to iterator over and the constructor index to use. There's a bit a hand waving there: for objects we will take the first construtor we defined (I'll implement multiple constructor support later), and the JSON values it contains in the map. We just ensure we get the values in the order the fields are defined (given by the constrFields function). For number we use the int constructor if our result type looks like an int, otherwise we use the float constructor. There is probably a better way to construct a number from a Double, but I still need to find it. For the moment we look if the type name starts with "Prelude.Int", which is arguably not very Haskelly. For Arrays, we need to recreate the (head,rest) tuple that gave me trouble when serializing, so we deal first with the head of the list, and put the rest afterwards. The empty list is the first constructor, a non empty the second.

Then to actually create the object we pass the values inside a State monad:
State f=(fromConstrM (State (\(x:xs) -> (jsonToObj x,xs))) cons)


For the list of values we convert the head from json and keep the rest as state. This simple line was the result of intense thinking, I implemented my own State monad first to really understand what I needed to do and then figured out that the State monad did the exact same thing. The final working code is always shorter that all the previous failed attempts!
We then only need to call the State function with the values we calculated earlier, and that give us our full code:

jsonToObj x=
fst $ f values
where
getArg :: a' -> a'
getArg = undefined
getType :: a
getType = undefined
myDataType = dataTypeOf (getArg getType)
(values,cons)=case x of
JSON.Object m -> let
c=indexConstr myDataType 1
in ((map (\x->fromJust $ M.lookup x m) (constrFields c)),c)
JSON.Number fl -> ([],if isPrefixOf "Prelude.Int" (dataTypeName myDataType)
then mkIntConstr myDataType (round fl)
else mkFloatConstr myDataType fl)
JSON.Array [] -> ([],indexConstr myDataType 1)
JSON.Array (x:xs) -> ([x,(JSON.Array xs)],indexConstr myDataType 2)
State f=(fromConstrM (State (\(x:xs) -> (jsonToObj x,xs))) cons)

Friday, June 20, 2008

Serializing Haskell objects to JSON

I'm trying to do some simple serialization of Haskell objects to save some state to disk. After tearing some of my hair out debugging parse errors due to silly code I'd written in Read instances declarations, I've decided to use another approach. I'm going to save objects as JSON, since I've already used that JSON library.
The first task is to write generic code that can serialize a Data instance to JSON. This has probably been done somewhere else, but I need to learn, right? So I took a deep breath and dived into Data.Generics.
I quickly rounded up the issues I would face. Most notably, Strings and lists are accessed without any syntaxic sugar, so to speak: Strings are lists of Char, and lists are made of two fields, the head and the rest. Of course, you say, but from that I need to regenerate String and lists of JSON Value objects.
So, to start, how to recognize Strings to treat them differently than other algrebraic types:

isString :: Data a => a -> Bool
isString a = (typeOf a) == (typeOf "")


There's probably better ways to do that, just tell me (-:

Lists (that are not strings) can be recognized with abstract representations of constructors, which are equals regardless of the actual type of elements in the list

isList :: Data a => a -> Bool
isList a
| isString a = False
| otherwise = (typeRepTyCon (typeOf a)) == (typeRepTyCon $ typeOf ([]::[Int]))


Now, transforming a list of the form (head,rest) to [head1,head2...]

jsonList :: Data a => a -> [JSON.Value]
jsonList l=
concat $ gmapQ f l
where f b
| (isList b)= jsonList b
| otherwise = [objToJson b]


For each element (the actual number depends on whether we're the empty list or not) we either reapply the same method, if it's the inner list or we simply transform to JSON

And then the actual method on objects:

objToJson :: Data a => a -> JSON.Value
objToJson o | isString o=JSON.String (fromJust $ ((cast o)::(Maybe String)))
objToJson o | isList o=JSON.Array (jsonList o)
objToJson o | otherwise=
let
c=toConstr o
in
case (constrRep c) of
AlgConstr _-> JSON.Object (Data.Map.fromList(zip (constrFields c) (gmapQ objToJson o)))
StringConstr s -> JSON.String s
FloatConstr f -> JSON.Number f
IntConstr i -> JSON.Number (fromIntegral i)


We first handle Strings, then list, then general objects using constrRep to distinguish between algebraic types that create JSON objects with the proper field names (using constrFields) and other types for JSON primitives.

And that's it for the serialization! The Generics package is not that hard to use but you have to look up examples to figure out how actually use the functions like gmapQ and such...

Now, I have to work on the opposite process: given a type and JSON data, reconstruct the objects... More Haskell fun!

Friday, April 11, 2008

The unintentional infinite list

The other day I was happily hacking away at some Haskell code. Same thing as always: think hard at about how to represent my problem in Haskell, then type the code quickly enough. Then launch my HUnit test. Tests doesn't return, just seem to be looping for ever!! Uh oh.
So I check my code, all the foldr and foldl and such, to make sure nowhere I create an infinite sequence. Nothing. So I took a deep breath and started the ghci debugger. I'm used to graphical debugger (like Java in Eclipse) but hey I managed to pretty quickly locate the offending function. Only a typo that couldn't be caught by the compiler. Since it's not the first time this has happened to me, here it is:
I tend to not be too comfortable with big one liner functions, so I revert often to several lines after a let instruction to cleanly separate each step of the computation. So when I repeatedly change some structure I tend to get:

fn a =
let
a1=fn1 a
a2=fn2 a1
in fn3 a2

and the typo there was a line like:
    a2 = fn2 a2


So I had typed in a2 instead of a1, and the compiler was perfectly happy, I wanted to create an infinite list, right? Er... That wasn't exactly my intention.
So I fixed the typo. Then ran my test. Which passed. Of course.

Tuesday, April 01, 2008

Me and my compiler

Pfiuu, long time no post, between my day time work, playing with Haskell and Lispy things (cool sutff like Clojure) and my extra-programming activities (yes, yes)...
I was just thinking about dynamically vs statically typed languages, since there is a lot of discussion about that on the web these days. For example, this article talks about refactoring in both static and dynamic languages. Well, I'm not a huge fan of all the refactoring utilities Eclipse give me, but there's one feature I use a lot: you know, when I change something, like the return type or the arguments of a method, my IDE helpfully adds little red crosses on all the source files that won't compile any more. So then I go through them and adapt the code.
Of course in a dynamically typed language I wouldn't get that, but since everybody has 100% code path coverage in their unit tests, it's just deferring the red cross marking a bit lower than the chain, right? Well, at work it takes 30 minutes to build our whole software from SVN (and only a few seconds to rebuild one individual module from inside Eclipse), and several hours to unit test everything (and have we got 100% test coverage?), so... Methinks I'll stick with something that can check that my types are coherent for me when I work on big projects...

Friday, January 18, 2008

Scraping my boilerplate: Generics instead of Records

I was talking last week about my trouble writing simple code to access and update record field in Haskell. While talking with justin about it, he suggested using parameter type for record object, so that the compiler would check that an update method would actually take as parameters the proper rating and the corresponding update function. That was cool enough, and that got me into the "Scrap your boilerplate" papers and Data.Generics modules. What I have now, using generics programming, is fairly simple and I think I'm getting closer to what Haskell code should be like.
First, Ratings: a Rating has three int values: the current level, normal level, and the experience points. What I do now is that each value is actually typed, and the Rating only holds a list of them:

data RatingScoreType=Normal |
Current |
Experience
deriving (Show,Read,Enum,Eq,Typeable,Data)

data RatingScore=RatingScore RatingScoreType Int
deriving (Show,Read,Typeable,Data)
data Rating=Rating [RatingScore]
deriving (Typeable,Data)

With that I can add an update method that only changes a RatingScore if the type match with the type provided:

addRS :: RatingScoreType -> Int -> RatingScore -> RatingScore
addRS t2 b rs@(RatingScore t1 a)
| t1==t2=RatingScore t1 (a+b)
| otherwise=rs


And a method that tells me if a score match the given type

getRS :: RatingScoreType -> RatingScore -> Bool
getRS t2 rs@(RatingScore t1 a)
| t1==t2=True
| otherwise=False


(note that addRS can be rewritten using getRS but we don't gain anything in code size)

I can then use Data.Generics functions to provide generic update and get functions:

addR :: Data a => RatingScoreType -> Int -> a -> a
addR rst i=everywhere (mkT (addRS rst i))

getR :: Data a => RatingScoreType -> a -> Int
getR rst a=
let (RatingScore t1 b)= head $ listify (getRS rst) a
in b


(There are probably other and maybe better way of writing these, but hey, the documentation is not very rich in examples...)

The level above Ratings are Characteristics: a character holds an array of CharacteristicRating:

data CharacteristicRating = CharacteristicRating Characteristic Rating
deriving (Show,Read,Typeable,Data)


Where Characteristic is again an Enum of all possible characteristics.

I define the similar 4 functions as above, except they filter on Characteristic first and RatingScoreType second:

addC :: Characteristic -> RatingScoreType -> Int -> CharacteristicRating -> CharacteristicRating
addC c2 rst i cr@(CharacteristicRating c1 r)
| c1==c2=everywhere (mkT (addRS rst i)) cr
| otherwise=cr

getC :: Characteristic -> RatingScoreType -> CharacteristicRating -> Bool
getC c2 rst cr@(CharacteristicRating c1 r)
| c1==c2=True
| otherwise=False

addCharacteristic :: Data a => Characteristic -> RatingScoreType -> Int -> a -> a
addCharacteristic c rst i a = everywhere (mkT (addC c rst i)) a

getCharacteristic :: Data a => Characteristic -> RatingScoreType -> a -> Int
getCharacteristic c rst a =
let cr=head $ listify (getC c rst) a
in getR rst cr


This is pretty cool: if I have a Character c:
getCharacteristic Strength Current c


Gives me the current strength! And a function can take a Data instance (a Character or anything else) and a Characteristic and do both testing and changing value in perfect safety!

Now I'm only just starting playing the Data.Generics, and more generally with Haskell program design, but this is cool. My RPG is not progressing fast, but the main game here is actually building it, not playing it!!

Friday, January 11, 2008

Nested records headaches in Haskell

I'm fighting a bit with Haskell records and named fields. This post has some valid remarks, but no real solutions. The main problem I have is managing elegantly nested records:
In my (embryonic) Haskell RPG game, a character is defined as a data type with several named fields (name, gender, traits). Traits is a collection of all characteristics (Strength, Dexterity, etc.). Each trait is itself a record with three values (normal level, current level, experience points). When an action is performed, not only we look at a rating value, we also update the rating experience as a result. So I want a function that takes a character, the name of a characteristic, and can update the proper characteristic rating.
With records
Traits { strength::Rating...}
I get a lookup function: a function strength that I can use to get the current value, so I can have a function like
testTrait :: Character -> (Traits -> Rating) -> ...
Where ... is whatever result the function returns (something like IO(Character,TestResult). But if testTrait needs to modify the record, I don't have a dynamic function to do it! And even if my code could hard code that "strength" is the trait I need, then the update mechanism is singularly cumbersome, since:
let c1=c{traits{strength{experience=1}}}
Doesn't compile (c is a character, I want to set experience of strength to 1). And if I want to modify the value (like do a +1 instead of setting to 1), then I need to unstack everything and rebuild it. Argh! Surely there is a better way?

The solution I have for the moment is that Traits contains only a list of Rating objects. Then I've defined an Enum with a constructor for each characteristic:
data Characteristic = Strength | ...
deriving (Show,Read,Eq,Enum,Bounded)
and I can have a method that combines fromEnum and !! to retrieve the right value. I can also have a little function that let me update a precise element in a list. But of course the type system does not guarantee me that every Character will have the right amount of Rating objects in the array!

It may be that my brain has been totally formatted by years of Java (in Java I could just pass the Rating object and it would get modified in place of course), but I just don't know what structure would give me total safety (enforcing that every character has the proper data) with no boilerplate code and no duplication. (I know I can define helper methods to do all of that, but I though Haskell would let me cut the amount of purely technical code needed and concentrate on the business).

Haskell syntax is not Java syntax; good or bad?

In this blog, the author expresses the opinion that an important part of a language popularity: Java was successful because it looked familiar to C++ developers, and similarly new languages should use Java syntax. This struck a chord: after all, I have started writing a pure functional language using Java syntax. I thought that having a similar syntax would help grasping the language better. But now I wonder. Not only do C++ and Java share a similar syntax, they also share some concepts (objects, etc...). If a language is intrinsically different (like a pure functional language with monads, say), then having a different syntax tells you straight away: warning! This is different, so not only you must learn a new syntax, but you must also learn a new way of programming.
So maybe having Haskell using a totally different syntax is A Good Thing. And it gives me a nice excuse to stop trying to create my own little language that looks a bit like Java but doesn't act like Java and concentrate on writing Haskell code.

Friday, December 21, 2007

Java and higher order generics

Funny coincidence: yesterday in work I was trying to find a way to express something simple enough in Java: I want a method map that takes a generic collection and return a collection of the same type (that is, passing a List should return a List, passing a Set should return a Set) with a different generic type. In Java you can have:

public <T1,T2> Collection<T2> map(Collection<T1> c,Mapper<T1,T2>

Where Mapper is an interface defining the method T2 map(T1 o);
There is no way I think in Java to express that if you pass a subclass of collection you get the same subclass back.

I tried things like <T1,T2,C extends Collection,C1 extends C
<T1>,C2 extends C<T2> and other crazy things that my compiler didn't appreciate.


You have to duplicate methods, and that's what we've done in work:

public <T1,T2> List<T2> map(List<T1> c,Mapper<T1,T2>
public <T1,T2> Set<T2> map(Set<T1> c,Mapper<T1,T2>

And of course a colleague needed a Vector because he was using an old library still using Vectors...
And then today I found that blog post, that point to that PDF document. Apparently you can do this kind of things in Scala and Haskell... Do I need to convince my company to move to Scala?

Friday, November 30, 2007

Haskell design patterns are (probably) needed

I was reading that post, and thinking: well when I start a Haskell project (for fun, yes, I don't use Haskell in work) I do wonder how best to design it. Yes I know about higher order functions, generics and such, but I don't think these low level constructs are enough to express, on their own, the design of the system as the design patterns from the GoF do. I would love to see patterns on how to allow extensibility, separation of concerns and such in Haskell. Years of experience in Java mean that I see a lot of things in terms of objects, inheritance vs composition, interfaces, etc, and not all of that apply in Haskell. I see a lot of low level algorithms in Haskell, but few software design papers (papers like this one are useful, we need more of them).

Monday, November 26, 2007

Structure of a functional Java, er, method

A method in FLOJ (remember, the functional Java based language I'm toying with) has a simple structure:
- a method definition 100% similar to a normal Java method: visibility generic return-type type parameters.
There are no exceptions, of course, since exceptions are things Best Done in Monads, once I've figured out
out I'll implement monads.
- a series of assignments of the form x=e where x is a variable name, and e an expression
- a return expression

For example:

public static String[] testMap(){
a=["toto","titi"];
a.map(String.toUpperCase);
}


Since the return expression is always the last expression, there is no need for a return keyword, but it's accepted by the parser. In the exemple above, the method returns the list of String TOTO and TITI.
Note also that the assignments do not allow nor require the type definition of the left hand side of the assignment. The type is inferred from the
return type of the right hand side expression (in the exemple above, a is a list of String). It's not as powerful as the full blown Haskell type inference but at least it saves some typing.

Of course, the generated Java code will add a sneaky final keyword to all the assignments, to enforce the fact that there's no variables in a functional language.

All in all, that structure makes the code easy to read and to understand: the sequence of calculations and the final expression yielding the method result.

I don't think my FLOJ language will ever be a full blown industrial-strength language, but I know that by implementing my own functional language I will learn a lot
more about functional languages than by just using one. Just implementing method pointers, type inference, combinator parsers and such, I understand more the why and how of Haskell.

Friday, October 26, 2007

A simple functional structure in Java

I have progressed a little bit in creating a functional language on top of Java, code name FLOJ (Functional Language On Java (-:). For the moment I'm only working on single files (I have a working parser), on the simple language constructs.
It's really interesting, because looking at very simple things make you think in depth about some issues that you may not really consider in Java proper. For example, this is the definition of a very simple structure:

package fr.moresmau.jp.floj.samples;

public class Simple(String data,int port){

}


So you can see that the package system is Java's and class definition are very similar. There are no constructor, so. Since null are not allowed (nulls are a huge source of bugs, I'll provide a Maybe object or something like that later),
the structure must have all its data filled in. If you want different operations to be done, you just create static functions that take parameters and create what you need, no need for several constructors. So the list of fields is entered straight after the name of the class.
Simple is a structure with a string and an int. It's easy enough to generate the constructor in Java:

package fr.moresmau.jp.floj.samples;

public class Simple{
public final String data;

public final int port;

public Simple(final String _data, final int _port){
if(_data==null){throw new NullPointerException("_data");}
this.data=_data;
this.port=_port;
}
...


The fields are immutable of course, so we don't bother with a getXXX() method, we just expose the field.
And you can then add setters that return a new object :

... public Simple setData(final String _data){
if(_data==null){throw new NullPointerException("_data");}
if (_data.equals(data)){return this;}
return new fr.moresmau.jp.floj.samples.Simple(_data,port);
}

public Simple setPort(final int _port){
if (_port==port){return this;}
return new fr.moresmau.jp.floj.samples.Simple(data,_port);
}
...


Note the null handling is not ideal, left for later. Note also we avoid superfluous creations if the data will not change.

So far, so good.

Then I decided to implement equals, so that equals is based on the data and not pointer equality:


...
public boolean equals(final java.lang.Object o){
if (this==o){return true;}
if (o instanceof fr.moresmau.jp.floj.samples.Simple){
fr.moresmau.jp.floj.samples.Simple co=(fr.moresmau.jp.floj.samples.Simple)o;
if (!this.data.equals(co.data)){return false;}
if (this.port!=co.port){return false;}
return true;
}
return false;
}
...


And with this of course the problem of overloaded equals method raises its head. If I want to allow subclasses to add more fields, my equals method won't work for subclasses.
If I check the exact class name in equals, subclasses that only add/overload methods will not be equals to superclasses.
So what can I do? I haven't decided. I could forbid subclasses to define more data fields (that's I think what you have in Haskell: you inherit functions from your type classes but no data).
I could also make the equals method final and not generate it for subclasses, but equality would then ignore the additional fields.
Another option would be to check the class name in that equals method and generate the proper equals method for all subclasses, but that may cause problems if we then extends the FLOJ class by a Java Class (which will be possible since we generate Java code).
But maybe it should be so, that a class is never equals to its subclasses? Returning equals between two instances that have the same data but different behavior (one instance has an overloaded method) is probably an error in the OO world...

Anyway, creating your own language is fun, I'm learning a lot and maybe I'll even end up with something usable!! I'll keep you posted on my progress.

Thursday, October 11, 2007

Generator (with yield) in Java

For some reason I was thinking about generators and the yield function (as found in Python). All this functional talk about infinite lists and such I suppose... So I had a go at implementing one in Java, which tied in nicely with my current reflexions about a java-based functional language and the need to provide concurrency out of the box. And another occasion to dabble with wait and notify in Java! After I've written it I found a similar looking implementation (but without the standard Iterator/Iterable interface support) and something on Google code that use bytecode intrumentation (why oh why). But still I like mine, that you can find here (and the unit test is here).
Basically the work is done in another thread and we call wait() when we do a yield. We conform to the Iterator and the Iterable interfaces, and we provide a stop method to actually stop the thread (say for infinite generators). Otherwise if the generator has not finished the thread goes on waiting forever. I've thought about trying to stop the thread when the generator is not used, but I don't know if it even possible with things like SoftReferences (The thread having a pointer to its runnable...).

Tuesday, October 09, 2007

My own Java-based functional language

I've been toying for a while with the idea of creating my own Java based functional language, if only to be able to see first hand the challenges in creating a functional language. The language I envision has the following characteristics:
- syntax close to Java: contrary to JHaskell or CAL, I want something that looks like Java, not something totally different
- Java type system: use the normal Java OO type system: classes with at most one superclass, interfaces. Maybe I'll run into issues but for the moment...
- pure functional and monadic: what I love in Haskell is the clear delimitation between what's purely functional and what's subject to side effects (IO, etc...). I'd like to have that in my language. I know about Scala, but Scala lets you mix functional and imperative code, I want something pure (and I don't like to add new very un-Java like keywords like def)!
- Java integration: there is no point of being implemented in Java if we can't reuse the wealth of Java code and libraries out there. Probably I'll need a way to distinguish somehow functional Java code (like the String methods) and not functional code, and wrap access to non functional code in a monad.

Now that's an ambitious program!! I've started some parsing and conversion to Java source files (hey, if Java can do some of the type checking for me...), but it's going to be a long road...
Of course, if such a language already exists, I'd be delighted to hear about it!

Wednesday, September 19, 2007

Parser Combinator in Java

Pffuii, I'm quite busy these days, hence the posting frequency has dropped. I'm in the process of playing with a functional Java based language (more on that in later posts, hopefully) and I decided to have a go at a little parser combinator in Java.
The end result works (I can parse things like Java class declaration) and looks a lot like parsec, but there is a lot of Java cruft that I'd like to remove, things that are hidden with the wonderful magic (I don't understand it well enough to call it otherwise) of Haskell monads.
For example:

try {
Character c=new Try(new Letter()).parse(input);
...
} catch (JCParseException jpe){
...


This code tries to match a letter in the input at its current position (the input variable) and does not consume any input if it fails. I don't like having to explicitly tell the combinator to parse the input, and I don't like using exceptions to indicate a parsing failure. Now, anybody has any great ideas?