What Would It Take To Make "Elm Embedded In Haskell" Available In GHC?

Haskell lacks what Elm has and Elm lacks what Haskell has. Both are arguably “best in class”, amazing technologies: Elm for the frontend and Haskell for the backend.

If they were a little more unified, Haskell and Elm together could offer a remarkably strong value proposition. If some differences were alleviated they could be a uniquely powerful combination.

Haskell and Elm are just different enough to derail a powerful synergy that could strongly motivate a much wider adoption of both technologies/ecosystems. Haskell used with Elm is an appealing combination but doesn’t satisfy those looking for a more uniform front-end and back-end language solution. Javascript and Rescript etc already offer this with perfect uniformity. If the proposed adaptation of GHC were implemented then the newly “Elm-retrofitted-Haskell” together with Elm would be surprisingly advanced compared to alternative “full-stack” solutions. It’s a shame that Haskell and Elm are currently just different enough to be missing out on what could be an amazing pairing.

Given that the Elm Language is, roughly speaking, a subset of Haskell with some differences, could GHC successfully/realistically be modified to provide an optional mode where the Elm language becomes embedded within Haskell? For features that overlap in Haskell and Elm, the Elm syntax/semantics would be adopted (other than strict evaluation). All the unique features of GHC Haskell that have no equivalent in Elm would continue to be available for use alongside the new Elm syntax.

To make this change, implementing Elm-style records seems to be the biggest challenge. Fortunately, Elm’s records are, from what I’ve seen, generally hailed as an improvement over Haskell’s records. Appearing later in history, presumably the design of Elm records benefited from newer research and greater historical perspective over what was available when people were engineering Haskell records. I’m not sure how much Elm’s choice of record semantics is an outgrowth of the underlying reality of Javascript or if Elm records are just generally/universally so great so that even the Haskell community would actually adopt Elm’s record’s for itself if it was as simple as just starting over.

Beyond records, Elm has the following syntactic differences:

  • Elm has multi-line strings: “”"…"""
  • Elm has a different import syntax
  • Elm’s type signatures use “:” instead of “::”, and likewise cons is “::” instead of “:”
  • Elm uses “List” instead of “[]” in type signatures
  • Haskell’s brace brackets “{}” could collide with Elm’s record literals
    Elm is pretty simple, are there other overlapping but differing features?
    **

Generally speaking, how realistic of an undertaking would this be? How much would your ballpark estimate be to pay someone to get it done? How realistic is it to just pay someone to make this kind of a change, considering the specialized nature of the work? How maintainable would this be? What would it take to adapt and maintain tools like the Haskell language server with these new differences?

If an Elm backend did get developed to maturity, it would likely be based on Node, but Haskell would be a superior host in terms of technology while also being much more culturally/spiritually aligned with Elm.

Haskell on the front-end seems that it will never quite rival the sharp, custom-tailored tool that is Elm. As it is, it seems Haskell is likely to narrowly miss out on attracting a much larger community of web developers. I say “narrowly miss out” because Elm, the near perfect catalyst is so close at hand.

Arguably we could also take a different approach, and make a version of Elm using a similar but more accurate subset of Haskell…but this seems like a poor direction as it would be trying to produce and popularize a slightly weaker (less tailored) version of something that already exists in Elm. Elm has already established itself. Elm has the advantage and momentum that a new, similar project is unlikely to rival.

The benefits would, I think, easily outweigh the cost of somewhat fracturing the Haskell ecosystem (with the “new”, alternative, Elm-based syntax). For experienced Haskell users this would hopefully just be a trivial annoyance if it comes up. For learners coming from Elm, the increased uniformity could make the difference between enthusiasm about learning “Elm-adapted-Haskell”, which would then be perceived as building on their existing Elm knowledge and experience versus them experiencing apprehension at being forever plagued by inconsistencies between Haskell and Elm. The new language combination would need a new name (I like the name “q”) and learning resources would need to be adapted or newly created. But on the positive side, courses could be created that teach Elm in the first year, and “q” (Haskell with Elm embedded) in the second year, and there would be continuity and consistency while moving between the languages. Elm would become, even more than it is already, a solution to the complexity challenge of learning Haskell.

We could make the new Elm-Haskell amalgamation also be a focal point for a culture which is heavily focused on basics and practical fundamentals.

Any thoughts?

1 Like

Elm is definitely the best-in-class FP language for frontend, and Haskell is definitely the best-in-class (pure) FP language for backend. If those two had been initially designed to be more uniform, that could have been really powerful. But they unfortunately weren’t, and now we’re in the position where the only way to make them more uniform is to fork one of them and make it more closely resemble the other. This is basically what you’re proposing here, to fork GHC. (Though I would argue that forking Elm makes more sense since it has a smaller community than Haskell, is newer, and is pre-v1.0.0, so breaking changes are more common). The trouble is that once you fork the language and change the syntax, it’s not the same language anymore, and you lose out on the status of being the biggest language. That means you have to start competing with all the other FP solutions out there. And there are plenty. If you want pure FP with isomorphic frontend & backend code, there’s already PureScript and GHCJS, and a whole host of impure FP languages (ClojureScript, ReasonML, ScalaJS, Fable, etc.). Since “q” would be a fundamentally different language than Haskell, why would we expect it to see more success than those solutions?

On a different note, I would also posit that the differences between Elm and Haskell have less to do with syntax and more to do with philosophy. The two take actually opposite approaches, where Elm deliberately restricts you to simple and easy-to-use concepts to be as approachable as possible, while Haskell makes the most complex solutions you could dream up a possibility. Trying to unify the Elm experience and the Haskell experience would be a lot more than just altering the syntax, but a change to the fundamental approach taken by these two languages. My guess is that Elm developers trying to learn Haskell don’t really get hung up on the syntax, but rather on all the advanced concepts you need to understand to be able to read others’ code and use libraries in the Haskell ecosystem.

5 Likes

What I mean to propose and ask about is whether it would be realistic to do all this as something like a GHC “extension” rather than a hard fork. If Elm records are superior to Haskell’s then the biggest part of this proposed alteration of Haskell would be an improvement, and the rest are a few syntactic changes that enhance uniformity with the rest of Elm.

I agree that the biggest challenge in learning Haskell when coming from Elm is not the syntax, but little syntax paper cuts would be wonderful to remove, and they do make a difference. It’s like when I get an actual paper cut, I’m very unhappy about the paper cut even though it’s not the biggest challenge I face, and yes you could rightly say I was overly focused on the paper cut. Even though “q” would be a highbred of Haskell and Elm it would probably attract libraries which are influenced by or harmonious to Elm’s libraries. For example, the way Elm doesn’t use partial functions like “head” in Haskell for example.

So in a nutshell, the suggestion is to improve on Haskell (records) and at the same time join/unite two powerhouse technologies/ecosystems without a hard fork.

This is just all my opinion, not the community’s as a whole.

Haskell isn’t obligated to be as syntactically similar as possible with Elm because, well, it is a different language with a different philosophy, despite the two having seemingly similar paradigms. In the same way that there’s no point in pestering Evan to add type classes and other Haskell conveniences, or Haskell-like syntax to Elm just because Haskellers are so used to it. (If you find [a] too bothersome, you could always make a type alias for it!).

From what I’ve read, people that came from Elm found it convenient enough to pick up Haskell, and really the hardest parts to learn about it is just the more advanced things it has to offer (like what @ntwilson has already mentioned, so I’m not gonna belabor this point any further). Although I can’t give any anecdotal experience with that because I haven’t picked up Elm at all but it seems to be a general enough consensus.

So I personally think that using the motivation of wanting Elm-like syntax in Haskell to justify fracturing the community is not a good idea because doing so to an already tiny community is going to do a lot of damage. Although the records situation is a valid concern, a proposal for an extension called RecordDotSyntax expected by 9.2 already addresses this that makes it so much easier to start with; not requiring you to reach for lenses early on.

1 Like

There is also a proposal about row types which would enable more convenient records: https://github.com/jvanbruegge/ghc-proposals/blob/row-polymorphism/proposals/0000-row-polymorphism.rst

@sekun I want to acknowledge your concern about “fracturing” the Haskell community.

My thinking is that this would improve the value preposition of using GHC and therefore draw in more people, and that this would outweigh the disadvantage of the fracturing effect of effectively supporting a slightly different second syntax.

My reasoning is that if Haskell and Elm together can do web stuff better then all others, then that could attract a much larger community to Haskell.

It’s really not just that I prefer Elm syntax.

Elm is, I think a tighter package and cleaner (in terms of a sharp, focused, simple solution) then React. It runs very fast and can be compressed to a significantly smaller size. It uses pure and non-partial functions. It boasts no run-time exceptions (in practice). It has incredible industry-standard-setting error messages. It has a successful (front-end) ecosystem.

I’m saying that maybe we could more effectively leverage the fact that there exists something that looks almost like a simple subset of Haskell that is really a shining star and a winning contender in the frontend space.

It is true that people can successfully learn Elm and Haskell. I am trying to propose and explore a solution to a problem. The problem is that even if it is possible to learn both, the Haskell community is almost certainly made smaller because a lot of people wouldn’t want to learn Haskell and it’s ecosystem and a slightly different version of Haskell (Elm) and it’s ecosystem when they have the choice to use Rescript. They might realize that Haskell and Elm are better technologies but they might not have the extra time to learn and do everything they already need to do plus learn the Haskell language and ecosystem and learn the Elm ecosystem. And you are right, people can either do all that or not and a more unified syntax will not fundamentally change that. But it would change the experience and perception of it.

I’m saying that maybe we don’t want to turn away the people who know they could do all that, but still prefer a solution without the regular paper cuts of relatively minor differences like why did I just type “:” instead of “::”. or use the wrong import syntax.

It’s like people would have to chose if they would like Haskell and syntax paper cuts or just Rescript.

I think a harmonious frontend and backend language is a powerful and valuable selling point that would do more good than harm. We have differnt experiences and priorities and this is all largely based on intuition and speculation so I can can understand how we can disagree here.

I guess you might be thinking that this wouldn’t actually attract a significant number of people to the Haskell ecosystem but the existing Haskell community would start writing code with two slightly different syntaxes which would indeed by definition be fracturing without any benefit, if that were the case.

I suppose the Node based Elm backends which are currently being developed could also be considered as fracturing the Haskell community, pulling Elm developers who want consistancy, but obviously we can’t stop them. We could chose to offer a better solution and invite them to use GHC. There are pros and con’s either way.

I guess one way of thinking about it is how much of the (future) Elm community is Haskell willing to give up to alternative Elm backends (external fracturing) in order to prevent any internal fracturing.

I think the main challenge in terms of unifying the languages is to get some kind of consensus that would prevent their fracturing again. Elm is very much Evan’s personal expression of design aesthetics, and long experience has shown that it’s not going to start managing use by a diverse community of people with different needs. It’s not going to maintain backward compatibility. It’s not going to work well with use cases like scientific computing that value operator overloading. It’s not going to support new abstractions for composable large-scale programs. It’s going to remain a single-purpose language for building small-to-medium-scale web app front-ends using one specific moderately-scalable architecture, and then do the best it can within that niche.

Creating a hybrid of Elm and Haskell that does both doesn’t fix that problem. Elm will just change to better express Evan’s design aesthetics, the Haskell community will be too diverse to follow, but the Elm community will go with Elm as they have for many breaking changes in the past. Haskell will continue to change, Elm will be unwilling to follow at the cost of greater complexity, and the Haskell community will go with Haskell. Then we’ll end up with a dead hybrid language, along with the same division between Elm and Haskell that exists today.

This is on top of the many technical challenges of unifying the two. (Edit: I misunderstood the original post, so the following is not relevant. Left here for posterity.) You mention copying Elm except for strictness and advanced features, but implementing high-performance Haskell with laziness and advanced features on top of a JavaScript engine is an unsolved problem. We have GHCJS and Asterius and WebGHC, but I don’t think anyone would claim these are comparable to the JavaScript generated by the Elm compiler. You’re going to lose those very same small-code and fast-runtime properties mentioned for Elm by grafting on the rest of Haskell. Something similar applies for other properties: Elm can have high-quality error messages because it limits overloading (e.g., type classes, operator overloading, …) and targets a very narrow range of code about which it makes assumptions about user intent. Keeping those high quality error while adding overloading and more diverse code is another vast and unsolved problem. You can’t just keep Elm’s good error messages while adding the advanced features of Haskell; you have to reinvent them.

There’s still something to be said for taking specific useful features from Elm, such as row polymorphism, and looking at how to add them to Haskell. People have investigated that. And there’s something to be said for implementing Elm’s specific design architecture in Haskell, and IIUC, Miso is an attempt at that and works pretty well. The communities can learn from each other, but I don’t see much hope for a merger.

11 Likes

@cdsmith

Yes, Elm has made breaking changes. I guess that’s an implied prerogative of pre 1.0 software no matter how much it may unfortunately hurt those who have adopted it. (I do hear that what you are saying goes beyond just that though)

My understanding is that for some years now, Elm’s basic syntax has not changed at all and that Evan has indicated he is exploring some ideas but what you see now is pretty much what you are going to get, and that statement was more about the big picture than just trivial syntax.

Elm has made an intentional choice to have an extremely spartan, minimalistic syntax and set of concepts with the goal of being an easy to learn language. Being easy to learn especially because of its great error messages, adds a lot of value to Elm and I think this proposal as it provides a kind of important solution to learning and propagating Haskell with its complexity (for learning in schools etc).

The simplicity and stability of Elm seems to make it ideal for this project.

I’m suggesting a kind of hybrid between Haskell and Elm so while the goal would be to have maximum consistency, it would be valid to say: “this is where we decided to follow the Haskell way of doing things”. We could take advantage of the overwhelming similarity and remove as many needless stumbling points as possible. If there were changes to Elm in the future we might choose to make further changes to be better aligned. Presumably, even if Haskell and Elm diverged in a way that would be relevant to this project, the consistency that we are able to implement would still be appreciated. The added syntax and conceptual consistency could lay a foundation for increased harmony and ease of transition between the two languages and ecosystems. It doesn’t seem necessary for the overlapping features to always remain absolutely perfectly consistent, just improved in a way that encourages community crossover and collaboration. I don’t expect either elm or Haskell to change its core syntax that much but if they did that would be an issue we would have to face and we would have the freedom to chose the best of either language/syntax.

I suppose Elixir is in some ways a similar project. At least in several ways:

  • both involve appealing to a community outside of the host ecosystem (in this case Haskell for Elm people and Elm for Haskell people, but also a wider audience for whom the added frontend-backend symmetry would hold value beyond the appeal of Elm and Haskell individually.
  • both involve transferring syntax, culture, libraries etc from an outside ecosystem to the host ecosystem
  • both have/had opportunities to fix some things in the host ecosystem (In this case: records, learnability, and a frontend solution are enhanced for Haskell people and for Elm people, they get a top-notch backend solution and all the things Haskell adds to Elm… )

We should just worry about merging GHCJS into GHC (prior to a WASM thing which we should also do) and not worry about the language itself, and more controversial things. That is easily the most bang for buck.

6 Likes

@Ericson2314 Fair enough. Do you think that would result in ghcjs becoming sufficiently lightweight?

GHCJS works fine enough for now. The main challenge are just people being scared it lags behind GHC. If we get more users across more orgs, then we can consider what optimizations make sense vs doubling down on WASM.

But the first step, via the GHCJS merge, is just making the Haskell for web frontend community more cohesive and bigger.

1 Like

I’ve had a bunch of comments on this (thank you), but none of the comments have really addressed my original question of what it would take to make this a reality? How much of this could be done as a GHC plug-in?

I don’t think this would work as a GHC plugin, because AFAIK plugins cannot change syntax.

I think the first step would be to reuse the Elm parser and type checker, but adapt it to produce Haskell.

I think there are three choices for which representation to use for Haskell code:

  1. A raw string
  2. Template Haskell data types
  3. Data types from the GHC API

Raw strings would perhaps be the easiest, but I think starting with Template Haskell data types is also easy and that is nicer. In the end if this is to be integrated into GHC then it will need to compile to the internal GHC data types.

I would start by implementing this as a quasi quoter in Haskell. (In fact, I have explored a similar approach for the UUAG “language”, but that also has some other challenges because it has embedded Haskell snippets)

You would also need to define the semantics of all the built-in Elm constructs. As you say records are a big difference, but I think a library like vinyl should provide similar functionality. Otherwise it is probably possible to create a new library that does match Elm’s records more closely.

Another difference is that Elm is strict while Haskell is lazy. So, you cannot immediately use standard Haskell types in your Elm code, but the other way around should mostly work. This also means that you probably have to rewrite many of the built-in functions.

1 Like
  • Elm’s type signatures use “:” instead of “::”, and likewise cons is “::” instead of “:”
  • Elm uses “List” instead of “[]” in type signatures

…as well as being strict - it seems like Standard ML had a greater influence on Elm than Haskell. It could make more sense to embed Elm in SML.

Instead of somehow “embedding” it in Haskell, would making Elm non-strict by default be an easier option? At the very least, that saves trying to merge the syntax!

For extra motivation, read the classic Why Functional Programming Matters by John Hughes.