Hacker News new | past | comments | ask | show | jobs | submit login
Introducing PureScript Erlang back end (nwolverson.uk)
174 points by pka on Feb 2, 2017 | hide | past | favorite | 31 comments



Looks like we just got compile-time type safety and higher-kinded polymorphism on the BEAM VM.


Well, it's complicated. I'm not trying to criticize this work, which is really cool, but it doesn't really tackle the hard part of types in an Erlang-style concurrent system.

To learn about the challenges of typing complex concurrent systems and some of the cool approaches for doing it, I highly recommend this talk by Zeeshan Lakhani: https://www.youtube.com/watch?v=-8jLRThHuFQ


Thanks for linking that.


I'm not sure I understand how static types and existing Erlang OTP patterns are supposed to work together.

What is the type of a gen_server? It can literally become anything.

What is is the type of become messages? http://joearms.github.io/2013/11/21/My-favorite-erlang-progr...


You can do success type-checking w/ dialyzer, so there's already a way to think about this. An instance of a gen_server is a pid, the become message in this example is a tuple of an atom and function.

http://erlang.org/doc/reference_manual/typespec.html


of course, but I wouldn't assume success typing (dialyzer) is compatible with static parametric typing, ala purescript


I'm not sure I'm seeing the gap. You get parametric types with Dialyzer + type specs. There are also several flags you can enable for Dialyzer to make its checking more strict and exhaustive.

Now that the escape hatch from type safety, that was impossible to avoid using Maps, has been mostly closed (and you're under no obligation to use Maps to begin with) it's not at all clear to me what you wouldn't be able to do.


I wonder how feasible it would be to develop PureScript back-ends for Swift (for the Apple platforms), Java (for Android), and C# (for Windows).


We recently added a way to dump out the compiler's intermediate representation as JSON, so it's actually very straightforward to create new backends by transforming that output [1].

The representation is fairly compact, so the requirements for a PureScript compiler backend are fairly minimal. You just have to translate all of the features of the IR:

- Functions with lexical scoping - Support for the primitive types defined by PureScript (we need to define some of these types more concretely in a specification) - A way to encode records. This could be something like JavaScript's objects, or just a map data structure.

The JS backend actually does more optimizations before code generation, but it starts from the same intermediate representation.

[1] https://github.com/paf31/24-days-of-purescript-2016/blob/mas...



Could PureScript become a more viable and practical Haskell?

I'd love to see it evolve in targeting more platforms, Python next maybe?


Maybe, but Phil (the author of PureScript) stated that he has no desire to compete with Haskell generally and he rather focus on polishing the JS backend.

There are already a few backends for PureScript[1] (including python!) but most backends went stale as the language progressed, maybe they'll get more love after 1.0?

[1]: https://github.com/purescript/documentation/blob/master/ecos...


It would be nice if they focused on the JavaScript backend a little bit. There's issues like https://github.com/purescript/purescript/issues/2577 that show the serious performance issues the language has with its primary back end.


I have to say that I'm constantly impressed with the level and tone of discussion in purescript development. That thread is a pretty good example. It looks like your wish is being fulfilled :-)


An active C++ backend. I'm now more and more interested.

I'm not suggesting competing with Haskell, but Haskell doesn't really target industry, never has and never will.

PureScript is very industry focused. With a solid Erlang and JavaScript backend, it gives you quite a nice single language for a lot of industry use cases, and with a possible C++ backend, might even work out for more cases.

Haskell pushes the envelope of typed FP even further, and adds laziness to it all. But I think there's room for something like PureScript to bridge the gap. If the Polish is there, and the tooling, and a strong commitment to stability, I can see a bright future.


> Haskell doesn't really target industry, never has and never will.

Why do you say that?


It's not that Haskell can't be used by industry, it's just that the language has mostly been used by enthusiasts and academia (that's not a bad thing). No big companies have really committed to making Haskell industry focused. Facebook has dabbled in it and even made some improvements to the GHC compiler but I don't think they are replacing swaths of their tech with Haskell.

I agree with the "never has" part of the statement but a little skeptical on the "never will" cause we can't really predict that. I feel like the language itself has been picking up popularity in recent years so who knows.


We can't predict that, and maybe it will one day, but I think that's unlikely. Academics will continue to want and extend Haskell more and more, and it'll enter into a conflict I believe between pushing the typed lambda programming paradigm further into research territory and having a slow and stable industry base that favors backwards compatibility, stability and performance.

There might be a way to have both sustainably, but I'm not sure why we'd want that.

I really wouldn't mind seeing Haskell continue to innovate and be a trial for innovative features, and have another slower Haskell like language which slowly and carefully brings back those features into itself once they've been proven mature enough.


> having a slow and stable industry base that favors backwards compatibility, stability and performance

I feel as if GHC addresses backwards compatibility and stability fairly well with new language features being gated by language pragmas. [1]

I don't write much Haskell in production, and what I do write isn't very performance intensive, but GHC's been pretty impressive vs. other compilers with languages at a similar level of abstraction.

[1] Foldable/Traversable in Prelude was a relatively large breaking change, and it was handled in a way that minimized the impact to existing code while still advancing the language.


> Facebook has dabbled in it and even made some improvements to the GHC compiler but I don't think they are replacing swaths of their tech with Haskell.

Their anti-spam and messaging evaluation system, for the whole system, is written in Haskell.


> Haskell doesn't really target industry, never has and never will.

There are contributors to ghc who add features or fix bugs with "industry use" in mind.

So your statement in its current form is a bit confusing to me.

Can you elaborate?


> Could PureScript become a more viable and practical Haskell?

Probably depends on the reasons why anyone might perceive Haskell as sub-viable or sub-practical in the first place (other than for transpiling to other languages with possibly "less FP" paradigms) --- I for one would be curious to hear them!


That's quite interesting! Perhaps you already know it, but it may be interesting for functional programmers who don't know Erlang : anonymous functions are not as efficient as they would be if they were declared as named functions (I read that it was because they're not inlined by the compiler, maybe someone with more experience could explain the inners of the compiler? =)


Anonymous functions in Erlang are lambda-lifted into named functions during compilation (during Core Erlang -> Kernel Erlang transformation IIRC). So there isn't much difference in terms of the final representation.

Erlang's compiler will do some inlining but it tends to be done at very specific points in time so lambda lifting might be done after the inline passes. I believe the lists module gets inlined most of the time though so I bet a lot of the lambda forms end up with very similar output when compared to hand-rolled recursive calls.

The real overhead comes with allocation of the "closure" state. There isn't much of any optimization to keep this in BEAM registers when the function call isn't inlined... but I might be wrong. It's been awhile since I've compared internal representations between different forms.

If you're curious, I'd be happy to provide some pointers on how to dig into these intermediate forms.


If they're not curious, then I am :)


I'll try to compile some references on a page but I gave this talk last year for an Elixir conference: https://www.youtube.com/watch?v=_HQfS8efVeg (It's not the best talk I've delivered on the topic but it's a start. I tried to cram too much into my timeslot.)

Robert Virding also has some great talks but I can't find the specific one where he discusses some of the lesser known compilation steps. At the end of the day, I learned the most from reading Erlang source code though. There's a lot to see in the Core Erlang compilation code: https://github.com/erlang/otp/tree/maint/lib/compiler/src

As to answer some questions elsewhere in this discussion on why BEAM code isn't targeted directly, it is poorly documented but you also lose out on a lot of these optimizations which happen at the Core Erlang stage. These are all things you'll have to reinvent.

There is debate on whether Core Erlang is a better target than Erlang but I'll skip that debate for now. Some languages, like Elixir target Erlang AST structures rather than Core Erlang while others (LFE) target Core Erlang.


Why not compile directly to BEAM bytecode?


Elixir, LFE and a lot of other languages past and present that share the BEAM use this approach. As far as I understand it, the BEAM byte code isn't documented all that well and emitting Erlang terms is more straight forward.

This approach also makes keeping your language up to date with the BEAM easier. If you implement against the byte code directly and the byte code changes then you have to make big changes in your compiler. By emitting Erlang terms you can make direct usage of the Erlang compiler (which should be more stable) in a later compilation stage. It's a similar situation for the LLVM and why they suggest you output LLVM IR and not bitcode.


Worth noting that Elixir and LFE apparently use different target languages (although you're correct, neither compile straight to BEAM).

Elixir compiles to Erlang, LFE compiles to Core Erlang, which is an intermediate form used by the Erlang compiler.


Right. And Elixir may target Core Erlang one day, for a hypothetic 2.0


One of PureScript's main goals is to generate JS that can be read by humans. I'm guessing the author wanted to follow the PureScript spirit when creating purerl.




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

Search: