Hacker News new | past | comments | ask | show | jobs | submit login
Frege: A JVM pure functional programming language in the spirit of Haskell (github.com/frege)
185 points by smikhanov on Nov 7, 2013 | hide | past | favorite | 107 comments

"Frege is thought as a substitute for this missing GHC port. While not derived from any existing Haskell implementation, it is more or less equivalent to Haskell 2010. Please see the wiki page that details the differences."

So now Haskell can produce native executable code, run in a JVM and as subset of it (https://github.com/faylang/fay/wiki) run in the browser. Now there is no excuse for me to NOT using Haskell ;)

Thanks for bringing Haskell to the JVM!

A large part of why I like Haskell is the ghc-specific extensions. TemplateHaskell, OverloadedStrings, DeriveGeneric etc.. Standard Haskell is (imho) much more cumbersome without them.

If you look at the differences page, it is equivalent in power, but does not have the same expression.

Pragmas now sorta start with @, and type classes are (in my opinion) kinda funky coming from Haskell.

Another difference not mentioned is given the use of recursion in Haskell and the JVM's lack of tail-call optimisation, I have to wonder how dangerous this is. I know Clojure has recur (I'm not a Clojure programmer) but unless Frege has something similar, I predict many an exploding stack.

It can compile to a loop. JVM can't optimize it for free at runtime. Scala has tail recursion elimination

What about tail calls for mutually recursive functions? My understanding is that Scala is not able to do tail call elimination in this situation. So the only situation where you can be sure that deep recursion won't overflow the stack is when a function is tail calling itself.

If Frege isn't able to do any better with mutual recursion then that might be a severe limitation on its utility. Scala users can work around the issue by writing loops manually. In a pure language, not so much.

Frege can handle mutual recursion.

The only problematic point is recursion through a strict function argument, like in:

    length (x:xs) = 1 + length xs

Scala provides trampolining via a library. Frege can do the same.

Please, scalac performs TCO in fewer cases than g++. Some JVMs are able to perform TCO, which is nice since scalac won't do it.

As a programmer who's getting annoyed and tired of Java's boilerplate, I welcome this. I went from Haskell to Clojure to JavaScript.

I loved Haskell the language. What I don't is third party libraries are usually directly or indirectly (through a dependency) tied to an OS. I've heard, even on irc's #haskell, that it's hard to reuse code unless you're on linux. Coming from Java, this is a deal breaker for me.

Then I tried Clojure. I liked it, but I found it very challenging to refactor and mentally debug my code. I missed all the benefits of static typing. core.typed seemed like an answer, but when you compare it to other languages it seems to triple the verbosity which is a real turn off.

JavaScript (via CoffeeScript) is a pretty good middle ground, but immutable state is nearly impossible. If I get lazy, it's so easy to go back to a OO/procedural style and I don't like that. That probably does have its benefits, but not when you're trying to learn a new programming paradigm.

I know very little about Scala, but I get a terrible impression from it. Where Clojure is about simplicity, Scala seems to be about complexity.

Since I learned Haskell, I wished there was a way I could use it and have it "just work" when I decide to use a library. Frege may be the answer. I've heard of it a long time ago. My concern is that I'd be 1 of 3 people who'd be using it. But nothing's perfect.

> My concern is that I'd be 1 of 3 people who'd be using it.

This concern is probably well founded. :)

And yet. Remember, you get Java source code from the Frege compiler, and once you pack up your JAR with Proguard, say, nobody will be able to tell you didn't write it in Java. (Well, slightly exaggerated, but you could have used some obscure library, who knows?)

So, if you have a small project, or some Haskell project without too many GHC extensions you want for some reason on the JVM, give it a try.

I suspect the GP is more worried about community support for the language than other people making fun of them for using it. :)

Sure, nothing can replace a big community.

OTOH, it looks like the Poster did have bad experience with Haskell community, though.

A small community is superior insofar as they are more motivated to help, and are more likely to take (critical) feedback into account.

I think it is fair to say that the Frege community (currently about 6 more or less active contributors) does its best, judging from http://stackoverflow.com/questions/tagged/frege and https://groups.google.com/forum/#!forum/frege-programming-la...

Of course, if someone demands, say, to implements GADTs or multi-param type classes by tomorrow, the answer will be gentle, but not affirmative.

Any data structures on the public API would have to be marshaled from whatever JVM language into fredge. Even sharing code between scala and java can be painful and obvious.

Not true.

I'm confused as to how javascript is a good middle ground. What does it give you that Clojure doesn't? You do mention the fact that it encourages imperative code and loses immutability. How does it improve refactoring or debugging?

That's a fair question and I don't understand it myself. Perhaps it's because the Firefox/Chrome dev tools are so useful. Perhaps its because I understand what the errors are trying to tell me. In JS I usually have a good mental model of the data I'm dealing with. I didn't have that with Clojure. I didn't have it in Haskell either, but the Haskell compiler would immediately get in my face about it until I fixed it.

It's a real shame that FFI-dependent Haskell libraries don't build out of the box on platforms other than Linux. If you really like the language, have you considered some workarounds for this problem directly? It may be a lot easier to do a workaround than to switch to a new language entirely.

It sounds like multi-platform support is important to you, how do you intend to deploy your software? In many cases, you can get away with rolling up binaries and not worrying about trying to actually build the software on your target machine.

I tried to get it to work, but it's really hard. Imagine you barely know the language and you barely understand how binary libraries work in linux and you're getting these errors that you've never seen before. You ask for help but it seems like you're the 2nd person on the planet who's ever experienced this issue. You read the post of the 1st guy, but for some reason his solution doesn't work for you and you don't understand why.

Most people in #haskell told me to switch to linux which seems like a ridiculous solution. I documented my struggle as another HN comment you can read here: https://news.ycombinator.com/item?id=5615683

Most people in #haskell told me to switch to linux which seems like a ridiculous solution.

Yeah, that's really unfortunate. This problem will continue to persist as long as people keep switching to linux to avoid it or abandoning the language altogether.

How long ago was your attempt and how did you install Haskell itself on your system?

It was a little over 6 months ago. I installed it from this: http://www.haskell.org/platform/

Ahh. Have you ever used MSYS+MinGW? It's pretty much a necessity for developing POSIX-based tools on Windows.

Scala is the most enjoyable language I've ever programmed in. Most of the complexity is superficial or shaped to the problem; there are a lot of features and they can be combined to make complex things, but each of them makes sense, and there's very little in the way of fiddly edge cases to memorize.

What other languages have you programmed in?

More than I could remember all of, but certainly Python, Java, C, TCL, Javascript, C++, ML, Perl, 6502 assembler. I've stuck my head around the door of Haskell, so to speak, but not written anything substantial in it; I haven't tried Clojure (I've never heard a reason to use it over Scala, and I've become very attached to powerful type systems).

"Where Clojure is about simplicity, Scala seems to be about complexity."

I have the same opinion. I would really like to try a haskell on the jvm but I'd prefer if it'd be strict instead of lazy.

It's interesting to compare this to CAL - an earlier Haskell-like language on the JVM that was a project of some of my former colleagues at Crystal Decisions/Business Objects back in the 00's: http://openquark.org/Welcome.html

I've worked quite a bit with CAL over the years and it has been used for some serious work. One of my big frustrations with it though has been the clunkiness of the Java interop, especially since this is one of the reasons you might choose to use a language on the JVM.

Looking at the Frege docs, I like the look of the way this has been handled - rather than using an FFI-style approach, things like Int, String etc map directly to Java types and Java classes can be used like ADTs, which would make life way, way easier.

Given the nature of the language calling Frege from Java is always going to be more complicated but it looks like they've done a nice "fluent" Java API for calling into the runtime.

Would be interesting to see how this performs relative to CAL, in terms of both speed and space.

> Would be interesting to see how this performs relative to CAL, in terms of both speed and space.

Indeed. Do you have some CAL installation somewhere to make a comparison? (The links I find are all broken.)

Unfortunately it looks like you would have to build from source. The best place for that would be Rich Webster's fork - https://github.com/rdwebster/Open-Quark - which is the version maintained by Indicee.

In the "How to build..." document it says I need Eclipse exactly 3.3.0

I am not going to install this, even if I would find it somewhere, hence ....

I imagine the documentation is completely out of date.

Anyway, if you don't want to look at it, that's your loss - while I don't think CAL has much of a future a lot of work was invested in it by a very talented team and there is probably something to be learned from it.

> Anyway, if you don't want to look at it, that's your loss

Actually, I did look into it several years back. If I remember correctly, CAL was not pure and still lazy. (An explosive combination, if you ask me.)

I like some of the differences where it was not constrained by Haskell's choices, like splitting up the Monad, Applicative, Functor instances, and namespacing of accessors. I also quite like the • for compose, with then some shims so that . works too if it's not being used for the namespacing.

Yeah, I'd like to see more languages using unicode identifiers. Seems to be a very unpopular approach, though :(

Haskell can do it: there's a library with common Unicode operators[1] (including ∘ for function composition) and an extension allowing you to use Unicode syntax[2] (things like → in place of ->).

I've seen these things used, but they're not super common. People still worry about not being able to input Unicode symbols in their editor! I personally think this is absurd in this day and age. Naturally, it's very easy to do in Emacs; somebody even wrote a Haskell input mode[3].

[1]: http://hackage.haskell.org/package/base-unicode-symbols-0.2....

[2]: http://www.haskell.org/ghc/docs/7.2.1/html/users_guide/synta...

[3]: https://github.com/roelvandijk/emacs-haskell-unicode-input-m...

Oh, nice! I setup XCompose to support rfc1345, so I have fast unicode input everywhere. I'm definitely going to experiment with that Haskell extension. I've done that manually before in ML with a preprocessor, but it was a nasty hack. A proper extension is much nicer!

EDIT: How many people still have trouble with Unicode input? Should I publish my XCompose solution?

It turned out that porting Haskell code was a nightmare when the (.) did not work yet. (You can't just replace each . with • unless you don't have any qualifed names.)

Today, it can be quite easy, in the best case you just Ctrl-C Ctrl-V

The conclusions of http://fregepl.blogspot.jp/2013/03/adding-concurrency-to-fre... lead me to believe that the author knows significantly more about Haskell than about either the JVM or concurrency. I hope that the language is able to attract a healthy number of contributors in those areas before it begins to accrete it's own idiomatic concurrency patterns.

Your comment would be more useful if you elaborated on these claims.

The section on forkIO vs forkOS is interesting because the author does not mention implementing green threads atop the JVM. It would be feasible for Frege and its core libraries to use an implementation of "green threads" based on Promises or CPS under the covers in order to implement a concurrency model indistinguishable from Haskell's.

While it is true that the vast majority of JVM code you interact with is blocking and expects to own whatever OS thread it is running on, that could be treated as a concern of FFI, where untrusted/blocking code in Java land gets dedicated OS threads (similar to FuturePools/execution-contexts for scala Futures, or how you would manually isolate blocking code for Erlang or Go FFI.)

Additionally, the comment dismissing STM seems like an afterthought, because there are at least three JVM implementations (Clojure's, Scala's, and Multiverse)

But the main comment I was referring to was:

  To do serious concurrent work in an JVM environment is
  different and it will thus require different knowledge
... which suggests that the author isn't interested in supporting Haskell's idiomatic concurrency model atop the JVM, and is instead fine with the status quo of blocking code.

> which suggests that the author isn't interested in supporting Haskell's idiomatic concurrency model atop the JVM

This is not quite true (I am the author). Yet I know my limits. Every contribution from the community is welcome, OTOH.

The point of the blog posts was only to explore how far one can get with what Java has.

There are at least two JVM lightweight thread libraries. Kilim [1] and Quasar[2] (written mostly by me).

[1]: http://www.malhar.net/sriram/kilim/

[2]: http://puniverse.github.io/quasar/

Cute name. I wonder to what extent the language has anything to do with Frege's work in logic. I mean Haskell's last name was Curry, and currying is a big deal in FP. Thankfully that wasn't named after Moses Schoenfinkel.

Actually, I've heard of German professors who used the word "Schoenfinkeln" instead of "currying". You sometimes get people who try to fight the English influence off at all costs ;)

If you want that in Haskell, there's a package for it


This is easy, Frege is (to my knowledge) the first one who mentions "functions, that take other functions as arguments".

In other words: higher order functions.

Hey, I'd love to use a language named Moses. You'd have all sorts of great puns and iconography available for library names.

That said, I always felt that "Finkel" would be a cute name for an FP language, service or library... I call dibs!

If that's the case, maybe you should name if after Raphael Finkel. [1]

Disclaimer: I had the privilege of meeting Dr. Finkel here at university a few times before I stumbled across his name in Wikipedia and in the front of a book in the library. Totally not biased.

[1] http://en.wikipedia.org/wiki/Raphael_Finkel

With its packaging system called Einhorn.

It very likely does. Also note there's a deep connection between functional programming and logic.


Let me introduce you to the legendary Tokyo Schönfinkel Appreciation Club:


I hate to say it, but when Schönfinkel Curried, he in fact Freged, as even currying was anticipated by Frege.

See here, for example: http://books.google.de/books?id=OeAPiy-6L74C&pg=PA134&lpg=PA...

Schoenfinkel was my second choice for a name my compiler project. Not a fan, huh? :)

A presentation about Frege from the author itself: http://fregepl.blogspot.jp/2013/08/talk-at-karlsruhe-functio...

Actually it is the link to the blog entry that contains a link to the presentation.

Anything that replaces the horribly overengineered and bastardized Scala travesty is welcome.

One of the things that make the JVM so cool is the easy interoperability of most JVM languages. It's good to have languages like Java (or Kotlin), Clojure, Frege and Erjang on the JVM, each with its own strengths. Each can remain relatively simple and consistent, and all interoperate and share libraries. This is far better than that "bastardized travesty" trying to be all languages at once, and ending up an incoherent mess, retaining little of the advantages of those simple languages.

I really wish this was strict.

I feel like most regular programmers could understand and benefit from using ML (or some similar language).

In Haskell, laziness kept the language pure while it was developing but now I'm not sure it should be the default. I like OCaml style opt in laziness.

For most people, they could get a lot of pretty vanilla typed functional programming language. Polymorphic type inference, algebraic data-types, pattern matching. That gets you really far.

There is Yeti (http://mth.github.io/yeti/), a JVM language from the ML family. I think it's close to a 1.0 release, and the compiler has been pretty reliable for a while now. I find it a delight to use.

I'm excited about this - but cannot seem to find a 'hello world' or any other actual code examples?

--Edit-- is it the exact same syntax as Haskell? Unclear.

It's cousin syntax, very close but not identical.

The author Ingo Wechsung outlines the ideas and concepts of Frege in the German blog 'Funktionale Programmierung': http://funktionale-programmierung.de/2013/10/10/frege.html

As an analytic phil PhD dropout and a Haskell lover I can say with confidence that (a) Gottlob Frege (the philosopher) was awesome (I still want a 'morning star != evening star' tattoo) and (b) Frege sounds lovely too. I'd actually considered writing something similar.

Looks really cool! Oh, it runs on the JVM. Hm, too bad.

What would you prefer? A language that doesn't need a runtime, like C? A language that has only one available runtime, like node.js? A language that has a choice of runtimes but there are incompatibilities between them like Python or Ruby? A language that has a choice of runtimes from a choice of vendors like Java?

"A language that doesn't need a runtime, like C?"

The language perhaps doesn't, but most actual programs do. I'm definitely not going to write my own standard library just because I can.

I wasn't advocating one choice or another. It's just the person I replied to just said "JVM ugh", which isn't necessarily reasonable.

A "Runtime" and a "standard library" are different things. There are a lot of (annoying to install) libraries for C.


Now what could the "RT" part possibly mean?

MS are unique in calling their C library a "Runtime library". Commonly, a support system that does GC and other automatic management for managed languages is called a "runtime", and the various common functions available to C program are called a "standard library". The difference is that in C, you can write a program that uses none of the standard library at all, whereas a managed program will use the "runtime" for doing anything at all.

I'd like something running on the CLR. Not because I think the CLR is very special; just because I really like Haskell but I have to work within a large ecosystem of existing .NET code.

Why not F#?

I've been playing with it some. It's nice, but I still prefer Haskell. I want to be able to separate pure from impure code, but F# doesn't seem to enforce that. (Unless I'm missing something?)

It doesn't. In fact, F# feels like it started off as a fairly pure functional language but some Microsoft PM said "it has to support every API in .NET" and so a lot of OOP stuff was bolted on the side. It feels like 2 different worlds in one language. You can easily get by never using the impure stuff but it's still there, taking up space.

F#'s design was almost completely handled by Don Syme, in MS Research Cambridge. It is highly unlikely some PM jumped in and insisted it must do things.

The OOP part is rather coherent; I'm not sure what's bolted on - any examples? In fact, things like object expressions do parts of OOP even better than Java/C#. Overall the syntax for OOP is rather concise and neat.

Having proper interop with .NET and hence the OOP is ... pretty key to making a successful .NET language. Otherwise you lose one major point of being able to use .NET libraries.

> The OOP part is rather coherent; I'm not sure what's bolted on - any examples? In fact, things like object expressions do parts of OOP even better than Java/C#. Overall the syntax for OOP is rather concise and neat.

I'm saying I'm not sure why the OOP exists at all. Someone else pointed at that OCaml has those elements as well, and maybe that's the reason. Just in my own use, I never felt the inclination to use the OOP at all, and their existence felt like this part of the language that I didn't understand, didn't want to understand, but was there nonetheless.

F# has its origins in OCaml which has the same set of properties (ability to write impure code and has an object system, albeit one that not many people use). F# replaced that object system with the .NET one.

A good question, remember Don Syme and Simon Peyton Jones even work in the same building...

> A language that has a choice of runtimes from a choice of vendors like Java?

That is like saying that we should developer Windows apps because you can always deploy using wine on other systems.

I'm not sure what you're saying.

If you're calling into question the portability of Java, then I can run the same bytecode on Windows, Mac, Linux, the browser (in theory) and, with a little transpiling, my Android.

If you're saying that that priority of decision drivers is backward, then I disagree:

If you want to develop a Windows app you start by saying "I want to develop something on Windows because my clients/customers run Windows". Then you work out how to do it on Windows.

If you start out saying "I want to write an app that does X" then you have the freedom to choose what balance of priorities affect you, including whether or not portability matters.

I believe he's trying to criticize Java for being owned by Oracle. The implication appears to be that alternative implementations are just compatibility layers for Oracle's technology like WINE is for Windows.

(For the record, I don't particularly agree with this. It seems like you could level the same criticism at nearly any language that has one person or stable group controlling it — for example, you could just as validly call Rubinius "WINE for Ruby".)

Do the MRI people own Ruby trademarks and patents? Did they use them to torpedo a free Apache implementation of Ruby?

IIRC Harmony was scuttled primarily because of OpenJDK — Harmony's major corporate sponsor switched its support to OpenJDK, and shortly thereafter the Harmony committee unanimously agreed to put the project in the attic. I don't think Oracle ever actually went after Apache.

Nope. Oracle denied Harmony a TCK license, meaning they had no license to Java patents (and trademarks). IBM switched to OpenJDK because of this.

Bingo :)

> A language that has a choice of runtimes from a choice of vendors like Java?

At least historically it wasn't much of a choice and I wouldn't put it past Oracle to continue in this fashion.

A runtime that can be used for a wide-variety of types of applications. JVM can really only be used for writing web servers and possibly daemons.

And building Twitter [1], and big-data next-generation databases [2], and android apps, and desktop apps, and big data [3], and as a platform for new languages (Clojure, Scala, Frege), and many more applications.

Really, the JVM can be used for anything that _computers_ can be used for, and it does so in a way that the code is runnable across all major platforms and still maintains a top-5 language performance spot, even beating C/C++ in some specific cases.

Why do you feel that the JVM is limited in its applications as a development platform?

[1] http://blog.redfin.com/devblog/2010/05/how_and_why_twitter_u... [2] http://www.datomic.com/about.html [3] http://hadoop.apache.org/

> And building Twitter [1],

Web server.

> and big-data next-generation databases [2]


> and android apps

No, Android doesn't have a JVM.

> and desktop apps

If you say so, I see very few of these in production.

> and big data


> Why do you feel that the JVM is limited in its applications as a development platform?

You can't write cli applications in a JVM language because the start-up time is too slow. Which means you can't compose scripts that call Java apps.

This is not just 1 type of application, it's the most important type of application by far. It's fundamental to how Unix operates. With Java you can't write small applications that do one thing well, you have to write big applications that are going to run for a very long time.

This is useful for things like web servers and daemons, but otherwise it sucks. It's why I can't get excited about JVM languages.

> You can't write cli applications in a JVM language because the start-up time is too slow. Which means you can't compose scripts that call Java apps.

You're right. In the case of small, fast applications designed to be called as part of shell scripts, the JVM does suffer start-up costs. Some testing on my personal machine shows the JVM to be 2x to 8x slower than a comparable Ruby or Python script in startup time. [1] Depending on the script, that startup time may or may not acceptable, and if the script runs for longer than a second, which is entirely possible for anything that goes beyond the local machine, the JVM will get progressively faster.

> This is not just 1 type of application, it's the most important type of application by far.

This needs more explanation. I've used Unix for many years, and I've definitely bought in to its philosophy of small and composable; It's a philosophy that in many ways mirrors functional programming. However, in my opinion, the most important type of application varies considerably by person. For you, the small, single-purpose applications may be what you use most.

And I agree, if you're programming for the Unix platform, the JVM would not be the best choice. Unix was built on C. A program that builds on that platform is probably a better choice.

But there are many more applications out there, and for any command-line program that operate in a time domain longer than 10 seconds, the JVM startup costs are mostly eliminated. This time-domain is very plausible for a command that operates on medium-scale databases or anything with network connectivity.

It's silly to completely dismiss an entire platform because it is not the absolute best choice for a single domain of programs.

I'm curious: What do you do where the short-lived, composable Unix functions are the most important programs?

[1] https://gist.github.com/bostwick/8ee1d4df9c7743f9efed

I think we simply approach software different. I feel that small, composable applications should be the default, and I nearly always start off this way. I've been involved in projects from writing a specialized version of cp, ETL processes, to developer focused but consumer-facing web applications and the first interface I write to anything I do is as a small cli application that works well with standard unix tools.

When you embrace this philosophy it doesn't particularly matter how good a language's ecosystem is, you have all of unix to interop with. For example, I don't care if a language has a good JSON parsing because jq[1] exists and is probably faster and easier to work with than just about any language's built in tools, even better than JavaScript itself.

With JVM you can't participate in writing software this way. Everything must revolve around the JVM and it's ecosystem.


I'd even say daemons are a stretch. Having multiple JVMs running at once would crush a lot of systems.

The JVM and the Java ecosystem are basically all about long-running backend services. It's funny when you consider Java's roots as a simple language designed to enhance web pages.

Really? Plenty of apps run on the JVM (everything from enterprise apps to games to IDEs etc...). I'm no JVM evangelist (I use Haskell with the GHC), but this is just a false statement.

"Enterprise apps" generally means "enterprise web apps", not standalone, deployed applications.

I've never seen a AAA game written in Java. The non-deterministic GC is a dealbreaker as is the speed and space constraints of eg consoles.

The OP is generally correct: the JVM is a niche technology in a way. The Java ecosystem basically specialises in web apps and backend ESB-type stuff (shuttling data very quickly between heterogeneous applications). Of course, this is a very big, well-paying "niche" so it's not something to be afraid of.

I'd say that minecraft is in the realm of "AAA" profit and userbase, though not "AAA" budget or graphics.

That is the only example I can think of though, and it is certainly a stretch. (also their X-Box version isn't Java)

Java doesn't need to have a non-deterministic GC. The Real-Time Specification for Java [1] has resulted in a number of JVM implementations designed for low-power, embedded devices; these implementations use a deterministic GC to provide hard real-time guarantees, and the devices they run on are less powerful than the game consoles from even a couple of generations back.

[1]: http://en.wikipedia.org/wiki/Real_time_Java

and Android apps...

Android doesn't run JVM.

Not technically, but practically speaking, you compile to JVM code & then it gets translated. This makes targeting the JVM & Android trivial.

Runtime code generation doesn't work on Android. This means all the reverse dependencies of cglib, for example. That is huge part of JVM ecosystem.

It's not trivial, this is why there are no JVM languages that really run well on Android.

What do you mean by that?

I would say compiled Scala runs well on the Dalvik VM.

All languages that do not need to generate (or load) class files at runtime should work well on Android. And that is because Dalvik does not run class files.

So then why don't we see more non-Java Android apps in the wild? We can only go off of open source apps, I've looked at quite a bit of those and have ran across only a couple that don't use Java.

Give an example.

If you don't need the JVM, you don't need Frege either, because there is Haskell.

The whole point of the Frege project is to make up (insofar this is possible for a single person who is not SPJ) for the missing Haskell-JVM port.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact