
Introducing PureScript Erlang back end - pka
http://nwolverson.uk/devlog/2016/08/01/introducing-purescript-erlang.html
======
proaralyst
Looks like we just got compile-time type safety and higher-kinded polymorphism
on the BEAM VM.

~~~
asolove
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](https://www.youtube.com/watch?v=-8jLRThHuFQ)

~~~
brightball
Thanks for linking that.

------
mwcampbell
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).

~~~
purescript
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...](https://github.com/paf31/24-days-of-
purescript-2016/blob/master/22.markdown)

------
didibus
Could PureScript become a more viable and practical Haskell?

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

~~~
gilmi
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...](https://github.com/purescript/documentation/blob/master/ecosystem/Alternate-
backends.md)

~~~
didibus
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.

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

Why do you say that?

~~~
slezakattack
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.

~~~
didibus
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.

~~~
thelambentonion
> 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.

------
Vosporos
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?
=)

~~~
strmpnk
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.

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

~~~
strmpnk
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](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](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.

------
the_duke
Why not compile directly to BEAM bytecode?

~~~
rubiquity
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.

~~~
macintux
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.

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

