Closed thkoch2001 closed 7 years ago
Hi Thomas,
I'll share my 2cts here, I don't know if those arguments are similar to @rahulmutt's one, so those remarks are totally personal, but I believe that in essence we both share the same vision.
First, Frege is not Haskell, or at least not GHC. I particularly appreciate the effort made recently in Frege in order to reduce the difference in term of syntax, etc... with Haskell, but still it is a completely different project from GHC and no code is shared.
The goal here is to hook into the GHC pipeline, the initial approach @rahulmutt took is by a doing STG
to JVM bytecode transformation, by leveraging GHC architecture we keep the door open to later try more sophisticated transformation (for example by starting directly from Core, and inline highly specialized interpreter, an approach radically different from Frege which could bring much better overall run-time performance).
Then even if Frege would have taken that approach about hooking into GHC, I'm still concerned by some design choices, I'll enumerate here two major ones (please free to correct me if I say something wrong, maybe things have changed since last time I dived into it):
GHCVM will be able to generate well optimized bytecode, but also thanks to FFI to find innovative and optimized encoding for data type, I think those are key to achieve great performance.
Even though the scope seems similar, based on those fundamental differences, I don't see how the works being done here could be merged with Frege (or vice-versa).
Both project have their own values and are facing different challenges, of course there is some overlap, and we will surely try to benefits from Frege/Scala/Clojure hackers experience here!
Hope that makes sense!
Also, GHCVM aim -in mid/long term- to target the CLR as well, see more details in https://github.com/rahulmutt/ghcvm/issues/1 I don't think Frege have any plan like that (nor a design suited for this purpose in my opinon).
@aloiscochard has pretty much summed up all that I wanted to say.
I'll elaborate a bit on the "No generation of byte code" bit. For the most part, you can almost generate any pattern of JVM bytecode using the Java language itself and it's easier to generate Java source code because javac
will ensure that the bytecode it generates is valid. But this changed with the JVM 7 release which included the 'invokedynamic' instruction. This instruction cannot be generated by any Java source code so if you want to use that bytecode instruction, you have to emit the bytecodes yourself.
This is why I am generating bytecodes even though the first version of GHCVM will not be using the 'invokedynamic' instruction. The plan is to use it in the future and having to rewrite the code generator to generate bytecode instead of Java source would probably consume a lot of time.
Moreover, the Java 8 release introduced lambdas which do generate the invokedynamic instruction, but you lose all the power of invokedynamic since you're confined to a single bootstrap method (the one that decides the CallSite for lambdas).
@xavier83 Yeah exactly. The reason it was named 'GHCVM' was to emphasize that a huge chunk of GHC is being used, just like in GHCJS.
@xavier83 I see the analogy but comparing Elm with Frege is misleading for people that know Elm but not Frege. As a Haskell, Frege has typeclasses, lazy evaluation by default, the typical standard library, etc. You can pick up any Haskell book and use it for Frege with only minimal, obvious changes.
@Dierk hmm, thought so too, perhaps purescript comes close.
@xavier83 yes, PureScript comes closer but still: not lazy - and this rules out the typical solution approach that one applies in Haskell using infinite data structures. It makes total sense in the JS world where your functions are predominantly event callbacks, though. Useful but different.
What are your goals for mixed language programming and interoperability on the JVM? One of Frege's strengths (from my point of view) is that it offers a straightforward and well-documented interface to other JVM languages, which means you can introduce a Haskell into your existing JVM-based world and use it alongside your current tools at work (if you're a JVM shop).
Re: invokedynamic
-- I wonder how much benefit you would get from it anyway? The Clojure folks have reviewed it in depth and decided it doesn't bring anything to the table (Clojure compiles down to static calls, for the most part, as does Frege by the way). Indy makes sense for languages like JRuby but perhaps not for FP languages?
Check out https://gist.github.com/rahulmutt/355505bce57c7c2cffd7d4cf5edddad4 where I discuss how to call Java from Haskell and call Haskell from Java. I need to update the README.md with all the documentation I've been doing. It's quite out of date.
I'm not sure how much benefit invokedynamic
will have, but one thought that comes to mind is the handling of thunks in a memory-efficient way, since evaluation of thunks is fairly dynamic (it goes through different states).
Thank you @rahulmutt -- I'll have to spend some time digesting that. I appreciate the detail!
No problem @seancorfield. Once you finish reading it, I have a follow-up question: 1) Would it be helpful to include 'foreign import/export clojure' and 'foreign import/export scala' as extra calling conventions that automatically do whatever is required to call Clojure/Scala functions within Haskell?
I think this would be a great step in integrating GHCVM in existing Scala/Clojure projects without pain.
I can answer your follow-up question without in-depth reading of the interop proposal: Clojure can generate a calling interface that looks pretty much indistinguishable from Java so having a Clojure-specific FFI doesn't really make sense, unless you wanted to natively support the dynamic Clojure runtime API: https://clojure.github.io/clojure/javadoc/clojure/java/api/package-summary.html (and I'm not sure that's really worthwhile given most Clojurians would expose a more Java-native API in their libraries if they wanted them to interoperate with Java or other JVM languages).
My understanding is that Scala is a little bit more work to interoperate with due mostly to name munging but it's now been about five years since I did any serious work with Scala so I'll defer to folks with more recent experience there.
@rahulmutt In the above gist:
instance (Extends a b, Implements b c) => Implements b c
Is that a typo? b implements c if b implements c
Thanks for the catch. I ended up removing the Implements
typeclass in the updated spec.
Besides the technical details of integrating with the GHC tools, is it fair to say, at a language level, that Frege is an implementation of Haskell '98/'10 on the JVM whereas Eta is an implementation of GHC (ie Haskell + GHC-specific extensions) on the JVM?
I mean if it were just about plugging into the GHC infrastructure it'd be two different implementations of the same language (eg Scheme has dozens).
It seems that your project is very similar in scope to frege-lang.org. Are you sure it would not be better to contribute to Frege?