We struggled a lot with this issue since we recently started a project with a substantial javascript interface. My anecdotal observation was that in the javascript application we got a lot more errors than previous applications that just used Snap and generated HTML code with Heist. We have not decided anything yet, but here are some of the possible solutions that we have considered:
Thin Javascript Wrapper
These are pretty unsatisfactory solutions for me. The improvement is a bit on Javascript, but don't come close to giving me what I get with Haskell.
A much more functional and secure foreground interface type
- Fay is the right subset of Haskell that compiles in Javascript. This definitely has some appeal, but does not give you access to all of Haskell. Recently, I heard that it does not support type classes, which, I believe, will quickly become an obstacle.
- Elm
- Roy
The problem with these solutions (as with the previous group) is that if your back end is written in Haskell, you still have an impedance mismatch because your interface language is not Haskell. This makes your code less dry because you have to define the same data structures in Haskell and the interface language. And when you change them in Haskell, you get no errors indicating where to change the front-end code. The application just breaks.
Compile Haskell for Javascript
The new game in town is ghcjs here. This is a very promising project, but I do not consider it viable for production, at least until the release of GHC 7.8. This will hopefully happen within the next week. Once 7.8 is out the door, you should still take into account that ghcjs is still very new. And even in a hypothetical scenario that it was a 100% feature, and the first release worked just fine, you still need to remember that you need to build enough infrastructure before Haskell + ghcjs is as effective as high javascript frameworks level such as Angular, Ember, etc.
UPDATE September 2016. Now, almost three years after I wrote this answer, GHCJS has improved significantly. There is even more room for improvement, but I used it for production applications, and it worked very well. This is especially effective when combined with the Reflex FRP library , which greatly simplifies the collection of reactive user interfaces.
Create Javascript from Haskell with EDSL
If you have a relatively limited problem, it is possible that all your applications will run on top of the EDSL that javascript generates. We already have a fantastic jmacro package to take care of low level Javascript generation issues. You can use this and generate code that uses any other javascript libraries suitable for your application. It can be javascript + jquery, D3.js or even code using a higher level javascript infrastructure, such as Angular or Ember. I tend to think that Angular will be much easier to generate code than Ember, due to its simplicity and stronger encapsulation.
Greenfield - Byte-Byte Designed for Functional Languages โโin a Browser
This is just a pie in my sky. I do not think this is really practical, because it will require a lot of work and it will be very difficult to get an adoption. But I like to at least mention the idea of โโcompleteness. Others noted that asm.js is almost like that. It may be so, but from the very beginning it would be nice to have things like tail-compartment optimization developed at the VM level.