I need to produce some benchmarks. Seeing as that web page is generated by a Haskell module which uses the compiler to produce the examples, it makes sense to also produce benchmark results.

I need to make the overall use for non-Chris-Done users more understandable, especially how importing modules work and the role GHC plays.

I need to flesh out the interaction between client and server (i.e. transparent serialization).

Need way more unit tests.

I want to put a web-based compiler for it online so that one can use it trivially in the browser.

It's really just Haskell, I call it "the Fay programming language" to refer to that-subset-of-Haskell, and maybe it can be marketed as a CoffeeScript alternative to non-Haskellers (and there is always the possibility of extending it beyond Haskell at some point, not sure I'd want to but it's a possibility).

I'm already using this in production, it works. But it's still alpha and there will be bugs.

Anyway, give it a little try, your feedback will let me know what I need to add to the documentation and examples. There is a lot to explain, I realise many things might not work as I have described. I really wanted to keep this private until it was perfect, but decided to share, so be gentle.

What would be great for me (and hopefully others) would a comparison of fay to the current "state of the art" of js client side development. Of course state of the art is somewhat subjective and fluid but for me at the moment this is:

require.js - for a module system

backbone

jquery

coffeescript - or some other js generator

I think these bits are the bare minimum to keep from going insane when doing js - but I guess the last one is optional.

Perhaps a port of one of the simpler backbone demos (e.g. the todo app) would be instructive? That's a minimal app that handles some traditionally difficult things to do client side (state, sync with the server, dom manipulation etc) it would be really interesting to see how fay handles something that takes more than a few lines. What do you think?

Also a couple of questions if I may.

Is there an FRP library, or can you use one of the existing ones (reactive-banana, sodium etc)?

Where would you consider the boundary between fay and existing js libraries? Would you do everything from scratch, use jQuery, use all your existing javascript libraries and use fay as a "better coffeescript"?

Perhaps a port of one of the simpler backbone demos (e.g. the todo app) would be instructive? That's a minimal app that handles some traditionally difficult things to do client side (state, sync with the server, dom manipulation etc) it would be really interesting to see how fay handles something that takes more than a few lines. What do you think?

Good point. jQuery I have already interfaced with and an existing UI library we use at work. Interfacing with Backbone or jQuery UI would be totally do-able, I'll think about whipping some demos up like that. Thanks!

Is there an FRP library, or can you use one of the existing ones (reactive-banana, sodium etc)?

I think they use rather more Haskell (and a bunch of extensions beyond vanilla Haskell) that Fay won't support yet. Maybe that's more for GHCJS or UHC at this point. For Fay it seems more feasible to latch onto an existing JS library or build a clone in Fay. Not sure that's what you wanted to hear but that's it at the moment!

Where would you consider the boundary between fay and existing js libraries? Would you do everything from scratch, use jQuery, use all your existing javascript libraries and use fay as a "better coffeescript"?

100% I would use jQuery/existing library. Here is a wrapper that I use at work, it's a bit like jQuery UI, very simple elements. I would never duplicate the work of jQuery, what a fantastic library! But I think you should definitely give it a nice type-safe interface which is what it lacks, if anything. It's possible to build your own things but I wouldn't do it merely for the sake of it.

I'm happy to adapt reactive-banana to work with Fay. Could you give a rough overview of what is not supported? IORef?

Note that the most pressing problem with any kind of JavaScript generation from Haskell is actually the missing integration into the cabal toolchain. Compiling libraries by hand with another compiler begins to suck really soon.

There is a Ref data-type which is basically equivalent to IORef. Well, it's just an FFI. It's more things like type-classes that aren't supported. Looking at the source, reactive-banana utilizes a lot of Haskell and Fay is very baby-steps right now.

For Fay it seems more feasible to latch onto an existing JS library or build a clone in Fay. Not sure that's what you wanted to hear but that's it at the moment!

Well there's always reactive extensions! I've been meaning to look into this for a little while to handle some of my more complicated event code. Perhaps an FFI interface to RX is the way to go initially?

Of course state of the art is somewhat subjective and fluid but for me at the moment this is:

Just a tip, you should have a look at YUI 3, it does require.js, backbone, jquery and more in a single, integrated package, and is in general better designed and more thought-through in my opinion. The primary downside is you don't get the wealth of jquery addons, although you do get CDN-hosted community-contributed modules that can be loaded like the core modules without any extra effort.

I'd love to see a complete FFI binding for YUI in Fay. I wonder if it can be auto-generated from the API comments...

Inline script blocks are probably not that usefull. I use them sometimes to send data to the client along with the initial page load, like translated strings, or to call some initialization code optionally depending on the server state.

I'm curious if your eventual approach will be to use GHC as more of library, by callings its compilation(typechecking) functionality instead of having to manually invoke both compilers. I could see making the process a lot cleaner that way. You may be way ahead of me or have a better way figured out, I just started looking at the compiler code.

Looks like exactly what I've been wanting from a Haskell to JS compiler otherwise, and happy to see you have made a ton of progress on this idea. As someone who has been using writing a lot of Javascript in recent months this is a great improvement from writing vanilla JS or Coffeescript.

This looks really cool - just a couple of questions - does unbounded recursion work and how did you get it to in js and are you planning to build the fay compiler in fay so we can have a web playground thing?

Unbounded tail recursion works. E.g. the forever function will iterate forever in constant space. This is because forcing thunks is in a limited kind of trampoline. I'm not sure building Fay in Fay is feasible without extending Fay a lot more, for now I'm happy just to have a JSON service. I think that'll be (responsive) enough for a playground.

If performance ever becomes a problem, this could actually become a good example where Boquist's GRIN could come in handy as an optimisation backend. It requires access to the whole program, but that seems to be standard in JS, so that's not a big downside. The advantage of it is that it compiles things down to first-order constructs and that may be easier to optimise for JS compilers.

You have successfully proven beyond a doubt how absurd, broken and unreadable javascript is.

Do you think it ever possible to create a browser that worked natively with haskell? How many man hours would that take? Having said that, I think the web paradigm is broken regarding documents that 'spawn' into apps. Quite how popups are still legitimate is astounding. Going higher I'd probably say the same about any OS GUI that wasn't a developed tiled interface like Xmonad. That maybe why so many apps seek to re-implement tabs.

Well, if it works, it doesn't work the way it does in Chrome, or the way a sane person would expect. You can try it in your Firefox with Firebug, set width:20em on one of the wide JS examples. It already has word-wrap:break-word. On Chrome this works, the text is wrapped. On Firefox it just floods out of the element.

I really appreciate the "strict subset" idea. I've been really excited by Roy and Elm, but the subtle (or sometimes not-so-subtle) differences from Haskell really, really bug me sometimes. For Roy this is understandable, given it is basically Typed JavaScript with Haskell-like syntax, but nevertheless unfortunate.

I'd appreciate an outline of which parts of Haskell are not included in Fay, and why. I suppose it's safe to assume that all language extensions are definitely out?

I'd appreciate an outline of which parts of Haskell are not included in Fay, and why. I suppose it's safe to assume that all language extensions are definitely out?

Any extensions to do with type-classes will not work. Fay has no type analysis inside it, making it basically untyped (hence the need for GHC), so it can't do type-classes yet. This makes implementation simple but we miss out on that stuff. But things like RecordWildCards I will add. Extensions like Rank2Types can work because that's just a type-system-only check, it's not something the compiler uses to determine dictionaries (i.e. runtime behaviour). I'd only need to allow the syntax in the Fay compiler. If you see what I mean. Monads may need to be similar to Roy i.e. sans-type-classes.

Awesome. I'd love to see a solution that makes it easy to communicate values between a Haskell-based server and Fay-based client.

For example, it would be nice to define the shared data-types in a single file that is read by Haskell and Fay, and have all the serialization/deserialization code generated automatically (for both the client and server sides).

Yeah, so there is no type-classes support, so there is no real show deriving.

But there is a function in the runtime, Fay$$encodeShow which external libraries can use to render your Haskell into a string. I just added it to the stdlib that comes with the runtime to make sure it's there. The things placed in hs/stdlib.hs are things that are somehow built-in in GHC and can't be defined within the Fay code without causing conflicts, so instead we pretend to use the GHC one for the type system, but provide our own implementation for the runtime. Short version: now you can use show.

External libraries can also access Fay$$encodeShow via Fay.encodeShow if they want to serialize something.

So when sending data to your server, you can use: show from Fay or Fay.encode from within JS.

When sending data from your server to your client, you can use Language.Fay.Show which renders your data type into a value that, when evaluated in Fay, gives you a Fay value. Use Fay.eval() to get that.

This part is not very well thought out. It works, but it's not great, needs more documenting. Here's what I am using at work:

A thought: you could use the XmlSyntax extension in HSE and have XML literals compile to DOM node objects.

Ultimately, I'd like the client-side and server-side code to be seamlessly interleaved, like in Opa. This could perhaps be achieved with a preprocessor, or at a minium there could be a QuasiQuoter for Fay similar to JMacro. I think we've discussed this on IRC. I'm not sure though if transparency is possible with Fay, though, since (by definition) Haskell and Fay are not the same languages. Perhaps you need something like GHCJS for true transparency, and then you get all the issues that come with it...

I assume you plan to eventually look at type-checking with the GSoC HTE project? I wonder, in the mean time, if the use of GHC can be made more seamless, and if GHC can be told to only type-check without compiling.

A thought: you could use the XmlSyntax extension in HSE and have XML
literals compile to DOM node objects.

Good point! If anyone wants that it seems easy to add.

Ultimately, I'd like the client-side and server-side code to be
seamlessly interleaved, like in Opa. This could perhaps be achieved
with a preprocessor, or at a minium there could be a QuasiQuoter for
Fay similar to JMacro. I think we've discussed this on IRC. I'm not
sure though if transparency is possible with Fay, though, since (by
definition) Haskell and Fay are not the same languages.

Indeed. Well certainly you can share code, but it has to be the subset that Fay understands, so you can have, e.g.:

and then you can import Comment.Shared in both Fay and Haskell, no
problem. So at a module-level granularity they can be interleaved. That
said, declaration-level interleaving, seems tricky.

I assume you plan to eventually look at type-checking with the GSoC
HTE project? I wonder, in the mean time, if the use of GHC can be made
more seamless, and if GHC can be told to only type-check without
compiling.

I wouldn't mind use HTE, indeed. Then I could support
type-classes. For my
workflow
the work with GHC is OK, but yeah I looked around, I could've sworn
there was a flag like -type-check-only for GHC but must've imagined
it.

I can add an optional GHC API type-checking inside Fay. Actually, I
think it would be quite effective because you don't really have to worry
about packages at the moment. I'll make a ticket to add
this. (I did start with
trying to use the GHC API instead of haskell-src-exts, but it's so
undocumented and quite difficult as an API, I also couldn't seem to get
hold of the type information that I wanted. But as a straight-up
type-check, no problem.)

I dislike the AST because it lets me generate complete garbage. Doesn't even distinguish between statements and expressions.

HJavaScript's AST is not much better, and its pretty printer is broken. Don't use it.

HJScript's (which relies on HJavaScript's AST) pretty printer differs, and is better, but I wasn't sure I wanted to use it this time, it can be quite restrictive and stop you being able to do something right when you've written half of your stuff in it, if it doesn't support something (e.g. ===) you have to patch the library, making it a rather annoying dependency rather than a helpful one.

JMacro is nice for writing JS. But manipulating it as an AST it would get in the way, I think. Kind of like when you're writing a TH macro and trying to use the [| … |] and [t| … |] syntax and finding that half of the time you're constructing the AST manually and might as well not bother.

I ended up defining an AST that suited my needs, it was simple and I found it was nice that it only contained things that the compiler actually used (and I could add some non-standard-JS constructs one might consider syntactic extensions but that really print to normal JS.)

Both jmacro and language-javascript seem to have pretty printers.

Dunno about jmacro, does it have a parser? language-javascript calls it a "pretty" printer, but it actually just prints the damn thing on one line. That's in fact why I wanted to use it, for its claimed pretty printer, which it doesn't have. The Print module in Fay did do pretty printing first, but then I changed it to a flat output deciding to leave that choice to the user.

Random idea: an "interactive" Fay shell that pretty-prints the resulting JS could be nice

I think JMacro was originally meant to be used for things like Fay. The main selling point really is the variable renaming which effectively gives you lexical block scope. However, thinking about this now I'm not sure Fay would benefit much from that if it wraps basically everything in a closure anyway. And if you can do without it, the generated code will be easier to debug anyway.

JMacro renders to a Doc, from the pretty package or in the future the wl-pprint-text package. Both of those packages are capable of pretty-printing a Doc over multiple lines with indentation and such (provided you used those combinators, which jmacro does).

Even if you don't end up using jmacro, it might be an idea to use wl-pprint-text yourself. I have submitted some patches to it that I'm hoping will get released sometime soon.

If you just want to use jmacro for pretty-printing then yes it has a parser, although it'll only parse the subset of JS that it implements, which may or may not be a problem.

Fay parses Haskell code using haskell-src-exts and generates JS from the AST, with a minimal runtime. It's sort of a direct translation in lieu of CoffeeScript, but with Haskell semantics.

GHCJS compiles from GHC's "Core" to JS, I think. As a result it can compile basically anything GHC can compile, although some things like IO might not make sense in the target environment (the browser). I suspect UHC works similarly.

The benefit of Fay is primarily (as I understand it) that it generates much smaller output code, at the expense of being less powerful. It might also be easier to debug generated code as it will be closer to the source code than what GHCJS/UHC generates.

This looks awesome, I did some thought experiment and decided the only way to have a sane Haskell in the browser was exactly this approach - especially type checking with GHC and translating separately. I decided I didn't have time to follow it, but I'm glad you did!

My only concern is that a lazy language will make it too slow in older browsers, and even an unavoidable performance hit in newer ones. Any reason not to support a strict evaluation mode?

My only concern is that a lazy language will make it too slow in older browsers, and even an unavoidable performance hit in newer ones. Any reason not to support a strict evaluation mode?

If indeed there is an unacceptable performance hit I don't see a reason not to support optional strict evaluation, technically speaking. A module-level strict evaluation mode, I presume? What's the precedent for that kind of thing?

Of course, qualifying all this discussion that there are no benchmarks (suite) yet… similar to the Fay→Javascript examples generated with the documentation I'll make a Fay vs JavaScript series of benchmarks with the spec of the machine, JS engine, etc. then we can resume the speed discussion with some hard numbers. (I like the idea of the web site being generate-able from the project source serving both as documentation/introduction and a report of unit tests/translations/benchmarks that a developer can view while hacking.)

There's also output-size to think about. I've been very Closure-Compiler-conscious writing this, I want to be sure that it compresses well, e.g. (here's an old paste back before it was called Fay) http://hpaste.org/raw/68191 and here is the complete compiler output including the runtime: http://hpaste.org/raw/68192 You can copy-paste that into firebug/chrome developer console and it works. Maybe I will add compression size to the docs output, too. Nicely, Closure can optimize away redundancy in some places, too, e.g.

Very interesting, Chris. I look forward to playing with this. I've been dissatisfied with the other approaches, so I've just been using JMacro and building up my own patterns over time. This looks like it may strike right at the tough parts.

I did it from this level as it was easier to maintain a correspondence. Core's output deviates significantly and I don't have a core parser. I think starting from the high-level syntax tree I can make some assumptions about where this is being compiled to. I should be able to maintain a source mapping too.

The GHCJS and Haste and UHC projects compile from the STG in the way you describe!

And I got tons of errors. Then I tried compiling and running one of the examples, during which time I did a sudo apt-get install nodejs, all of which worked flawlessly. Then I tried fay-tests again and they worked. So I'm guessing that fay-tests rely on node being installed? Perhaps you should clarify that in your docs.

Thank you. I think fay has great potential. It seems usable even at this early stage, compared to the hurdle of setting up ghcjs/uhcjs. The simplicity might help it gain the traction it needs. I just hope it won't be abandoned.

I think this will be a case of “fast enough”. I don't intend to write ray tracers but if Ruby is fast enough for people then so is this. I found that in v8 my tail-recursive fibonacci function ran faster than in GHCi. But I haven't really started on optimization which is a whole different interesting aspect. Benchmarks forthcoming.

How would you improve on that? I also really dislike having to pass in a Double / but I'm not sure what's the cleanest way, either conversion Integer to Double or Integer to String whatever is better after conversion. Yeah, and of course the return for array access should be Maybe Element.

First, congrats on getting this far, nice work. I think double is fine, all numbers in JS are double anyway.

I would improve by adding more foreign constructs: foreignGetProperty and foreignSetProperty, I think. As in here. If you have a github account you can enable notifications for that ticket and you'll know when I've added it. Or you can try adding it yourself. ;-)

Not sure how to turn the "possibly null" value into a Maybe. Lists are easier because they can be listToMaybe'd. Hm.

Eventually a (hopefully thin) layer around basic DOM and all the API magic a browser provides will emerge; my personal play target (but I'm very short on free time) is definitely IndexedDB

Unless FFI is extended with massive injection powers (think full text with arbitrary variable substitution), these API's will always come with some additional JavaScript helpers (which need some way to be included)

However packaging is solved: I think if the result of a Closure run essentially removes the boilerplate we're in excellent shape

Very exiting project.. Nice it is 'just' Haskell. One to follow closely.

I think a year from now the yesod/snap frameworks will have good implementations of one-or-more of these Haskell(-like)-to-JS compilers as part of their tool chain, allowing us to share sever and client side data structures.