There's also Fay <https://github.com/faylang/fay/wiki> which provides a lighter-weight compilation of Haskell to JS, omitting stuff like threading and type classes.
Nice thing about Fay is you can read the generated javascript and see the 1:1 correspondance to the haskell code. This can be a nice way to get an intuition abvout how thunks are used to implement eg, infinite length lazy lists in haskell. There is also a live IDE <http://ide.fay-lang.org/>. I think this makes Fay an excellent teaching tool.
The way it seems to be shaping up is that ghcjs will be used for big serious projects where a javascript runtime that is measured in (IIRC) megabytes is acceptable and the full power of haskell is needed. While fay will be used as glue code for projects that are mostly written in server side Haskell and want to run some code in the browser, with access to the same types used on sever-side to eg, make AJAX nicer. Fay's entire runtime is 16 kb (unminified; with minification and other size optimisations a complete program can be as small as 3 kb) <https://github.com/faylang/fay/blob/master/js/runtime.js> which makes it work well in these niches.
It's been quite exciting to see all this activity around functional programming languages that target JavaScript. It's worth comparing both the GHCJS and Fay implementation approach with ClojureScript which has no runtime and ships with a full suite of efficient persistent data structures out of the box. It is also capable today of generating very fast code with little overhead over hand written JS http://swannodette.github.io/2013/06/10/porting-notchs-minec... (and is in fact why the persistent data structures we ship work so well).
Haskell's type system is crafted for Haskell and core.typed is crafted for Clojure. I don't see how they can be compared given how different the two languages are.
I'd say your statement is not true, type classes arrived early on and adjustments needed to made. I imagine adjustments will continue to be made as Haskell evolves as a language.
It is true that Haskell & its type system evolve together whereas core.typed must follow Clojure wherever it may go.
turing complete, i.e. you can do type level computation
Turing completeness → computation, but the converse is not valid (i.e. computation → Turing completeness is not necessarily true). e.g. GADTs allow for some amount of type-level computation, but they do not in and of themselves form a Turing complete system.
Alas, looking at your link, it does seem that Haskell's type system is sadly Turing-complete.
correct, "turing complete, i.e. you can do any possible computation at the type level."
I don't know if I feel joy or sadness, but I have the feeling that if type level computation is allowed, then it's better to be turing complete than falling short while giving the illusion to be useful.
As for the practical applications of a powerful type system, I know about this (but I would be interested into finding more examples, as most of the information about that is very theoretical):
Code size is pretty big currently indeed. The highest priority is to make sure that we get all required patches to support GHCJS merged into GHC, before 7.8.1 is out. GHCJS is a standalone, cabal installable compiler (it uses the GHC API), but some features, like the "foreign import javascript" FFI need some minor changes in GHC itself.
We haven't really spent much time optimizing for code size yet, and there's still lots of low hanging fruit. We will never reach 3kB minified though, for example the JSBN library (that we use to implement Integer) alone is a lot bigger than that.
The GHCJS linker does tree shaking: Only functions that are reachable from main are included in the result. We have some plans to extend this a bit, an old version already had incremental loading, but that has not yet been implemented for the new code generator.
If you're really careful and not use anything from base that might use an Integer ;)
Currently non-Haskell dependencies are managed per package, so if anything from integer-gmp is linked, it will include the whole JSBN.
If you want to weed out the unused JSBN part, you can use closure compiler (although the new code generator will probably still have a few incompatibilities with it).
You can use the Integral class (when compiling, the instance gets converted to an extra dictionary argument, if you never use the instance the dictionary will be unreachable)
But Integer is really hard to avoid in general, for example the Show instance for Double depends on it.
I like Fay, but I thought the no-typeclasses thing was attributed to the fact that they used GHC as a front end and unwinding them out of GHC Core was to tall of an order for the time being? The Github page/discussion seemed to say as much IIRC. I'd really like to have typeclasses in Fay. Like REALLY like to have typeclasses in Fay.
Also threading in Haskell isn't a first-class thing. I'm not sure what you mean by that. How does one omit threading if it's not really part of the language spec to begin with? Care to expand?
> How does one omit threading if it's not really part of the language spec to begin with? Care to expand?
Not the OP but I can't resist answering. Threading isn't really part of the language proper, but as a lazy language can make flow control from language or library indistinguishable that isn't a very important distinction.
What matters is that GHC has an excellent threading implementation in its runtime and that the compiler has the primitives to build the Haskell concurrency libraries on.
I never really understood how Fay users could avoid using typeclasses, since it means (presumably) avoiding functors, applicatives, monads and all that other Haskelly stuff.
data ApplicativeI f =
AI { pure :: forall a. a -> f a
, ap :: forall a b. f (a -> b) -> f a -> f b
, _FunctorI :: FunctorI f }
data MonadI m =
AI { bind :: forall a b. (a -> m b) -> m a -> m b
, _ApplicativeI :: ApplicativeI m }
return :: _MonadI m -> a -> m a
return (MonadI { _ApplicativeI = ApplicativeI { pure = fn } }) = fn
Almost, but that's not extensible: I can't declare some new typeclass Foo and then declare that every x s.t. Monad x is also Foo x without editing the definition of Monad.
I hear ARM support will be standard in the next GHC, and there currently are ports and cross-compilers. Unless you're specifically talking about ghci, which I agree needs to be ported, though that hasn't happened for the browser yet. It's possible a project like this could help that happen, though...
There are ports of ghc to both Android and IOS. I've run ghc directly on Android. ghci not so much, so you're technically right about there being no interpreter.
That's awesome! I have played a lot with Scala and Android, and type safety, options, futures really improved the development on Android (less code, less bugs).
I would be curious to try Haskell on that platform.
Exactly! As I understand it, the moment js gets nice things like tail calls or concurrency, with very little work ghcjs can too! I'm really really excited.
You don't need tail calls in JavaScript in order have them in a language that compiles to JS. The tail call can be compiled as a while loop. This is what Scala does on the JVM (and presumably what Scala.js does as well).
This only works with calls that can be resolved at compile time (unless you mean a trampoline). That happens to be most of the common use, which is great, but it's not perfect.
Trampolines still work, albeit with a pretty substantial perf penalty.
Well then I dream of a day when an ecmascript revision makes the breaking changes needed to fix this. Or some sort of clever hack works around that constraint
GHCJS currently uses a trampoline, but all calls are in tail position, so when this gets implemented we can easily generate code that uses native JS tail calls.
Like GHC, GHCJS uses its own stack for non-tail calls.
I think native code GHC has its stack in the standard location, though it manages it explicitly (as most native code languages do). (I'll double check the ghc source later to make sure i'm quibbling correctly)
As someone who is very familiar with purely functional languages and with multiprocessor synchronization, I must ask, why would anyone want to use any of these things in Haskell? Aren't two of the primary benefits of Haskell the ability to auto-parallelize, and not needing to reason about state?
"Purely functional" is a misnomer. A better description is "typed effects". Haskell doesn't forego effects, it types them. You still have imperative destructive updates if you need them (e.g: to avoid a logarithmic complexity hit, or a constant performance hit). You still may want to write imperative programs, often-times as the backend of a pure functional interface.
Haskell is actually quite good at it, and jokingly referred to as "the world's finest imperative language".
Haskell doesn't have auto-parallelism. There are some excellent libraries for parallelism (strategies, DPH, repa) but they take some work. True auto-parallelism (a la Parasail) is far more difficult to get right (often due to granularity of work units).
Where are all the people saying that we should only ever use Javascript in the browser? Mysteriously missing now that the language discussed is Haskell?
Nice thing about Fay is you can read the generated javascript and see the 1:1 correspondance to the haskell code. This can be a nice way to get an intuition abvout how thunks are used to implement eg, infinite length lazy lists in haskell. There is also a live IDE <http://ide.fay-lang.org/>. I think this makes Fay an excellent teaching tool.
The way it seems to be shaping up is that ghcjs will be used for big serious projects where a javascript runtime that is measured in (IIRC) megabytes is acceptable and the full power of haskell is needed. While fay will be used as glue code for projects that are mostly written in server side Haskell and want to run some code in the browser, with access to the same types used on sever-side to eg, make AJAX nicer. Fay's entire runtime is 16 kb (unminified; with minification and other size optimisations a complete program can be as small as 3 kb) <https://github.com/faylang/fay/blob/master/js/runtime.js> which makes it work well in these niches.