Sky – an Elm-inspired language that compiles to Go

(github.com)

167 points | by whalesalad 17 hours ago

20 comments

  • flossly 3 minutes ago
    I think you have an interesting spot in the design space here...

    Have you seen Lamdera? They have a way to use Elm on the server-side that is supposedly acceptable to the Elm-BDFL Evan Czaplicki.

    https://lamdera.com/

    This talk explains it well: https://www.youtube.com/watch?v=4T6nZffnfzg

    Sky does all on the server (more popular lately with HTMX and LiveView), where Elm+Lamdera is basically 2 project and Lamdera ties you into a propietary-ish ecosystem.

  • melodyogonna 14 hours ago
    That's two new languages compiling to Go making HN frontpage in as many days. It seems people like everything about Go except the language itself. Me? I like everything about Go including the language, these transpiled languages are interesting though.

    But I keep wondering if they could integrate at a lower-level than the source code. Like how JVM languages integrate at the bytecode level, or LLVM languages at the LLVM level

    • lenkite 3 minutes ago
      I like Go as well, but I wish the Go team were slightly less conservative about language changes. Only asking for 10-15% less conservatism. It is OK to add one proper new language feature and one good standard library package per year. Or deprecating one language feature and one stdlib package every 2 years.
    • sbrother 7 hours ago
      > people like everything about Go except the language itself.

      Thanks for putting so succinctly exactly how I feel about Go!

    • MichaelNolan 13 hours ago
      > But I keep wondering if they could integrate at a lower-level than the source code.

      I’m sure they could, but targeting go source code has the benefit of giving early adopters an escape hatch. If it targeted LLVM directly, I would never consider using this at work since the risk of it being abandoned is too high. But since it targets go source, I would perhaps consider it for some low importance projects at work.

      • seabrookmx 12 hours ago
        The standard go toolchain doesn't use LLVM. Go has its own assembly format and machine code generation.
    • nu11ptr 12 hours ago
      > But I keep wondering if they could integrate at a lower-level than the source code.

      Unfortunately nothing below source code level is stable, so they would constantly be chasing changes after any Go release. I personally wish they would focus on making it accessible, as Go actually has a nice runtime and would make a good language target.

      • melodyogonna 1 hour ago
        Aha! That would explain things. I was wondering if the Go assembly at least is stable and documented, couldn't really find anything
    • onlyrealcuzzo 12 hours ago
      What was the other one?

      I'm working on a language that transpiles to Zig with a custom Go-like runtime (and no garbage collector, Rust-style Affine movement instead).

      Sky seems quite cool, as it's additive to Go in interesting ways.

      I originally considered keeping the GC and just transpiling to Go so I didn't need to write a Runtime.

      Go rules! It really does. But I HATE writing/reading Go.

      So I'm glad more people are doing this!

      • gottorf 7 hours ago
        > Go rules! It really does. But I HATE writing/reading Go.

        Same. I love the Go toolkits, the compile story, the speed at which it compiles, its backwards compatibility, the fact that stale Go code 10 years old still compile and run, etc., just don't care much for the language itself.

        I wonder if the positive attributes of Go aren't compatible with clever types and other developer-friendly features?

        • throwaway894345 6 hours ago
          It’s mostly that Go was already pioneering how to build a programming language that had an amazing scheduler, garbage collector, compiler, package manager, formatter, etc. They spent all of their “innovation budget” on the most important—and most neglected—features of any programming language and allowed the language itself to be pretty boring.

          Eventually Go’s runtime and tooling will be bog standard and everyone will think of them as boring and then people will start building more exciting languages on top of them. Assuming AI doesn’t blow everything up.

      • styluss 12 hours ago
        • onlyrealcuzzo 11 hours ago
          Awesome, this is very close to what I originally considered.
      • melodyogonna 1 hour ago
      • osigurdson 9 hours ago
        I understand the motivation as I don't really like writing Go code. Interestingly, I don't mind reading it though (as long as the if err != nil isn't too exhausting).

        A transpilation step though? I'll accept that in Typescript (barely) but not for any other language really.

    • gethly 51 minutes ago
      Go is simple. People like complexity. So the write abstractions to feel better about themselves.
      • phplovesong 1 minute ago
        Complexity does not equal language features. Sometimes simple is good, but sometimes simple just simply means more bugs in your code.

        As a prime example, Go unwillingness to add even the most simple enum kind of type. Having enums (ADTs) with exhaustive pattern matching is NOT complex in any sense or form. It just takes away so, so many bugs you would normally see in production code.

        One other low hanging fruit is the fact that zero values are in 90% of all cases not what the dev intended. Sure, the mantra goes "make them useful" but thats hard. How to you know if a value (int) was zero initialised, or if the user did in fact input zero as value. No matter, you will need to validate every one of these "zero values" if you want some sort of robustness.

    • ksec 13 hours ago
      If we think of Go as different kind of C, then having Go as a compiled target seems to make sense as C is a compiled target.
    • throwaway894345 6 hours ago
      LLVM and JVM have stable interfaces. Go has an intermediate representation but it isn’t stable. Anyone who wanted to depend on it would be on the hook when the implementation changes.
  • 1-more 12 hours ago
    I will add this to my list of Elm-inspired tools that call to mind Brian Eno's quip about the first Velvet Underground album: "I think everyone who bought one of those 30,000 copies started a band!" With Elm it feels like it's 1% of Elm users creating a language.

    https://quoteinvestigator.com/2016/03/01/velvet/

    • bbkane 4 hours ago
      You should publish your "Elm-inspired tool" list- I bet it's pretty large. Off the top of my head: iced, react redux, bubble tea (Go lib), Roc lang.

      I'm sure there are lots more. I'm still waiting for someone to write an "Elm retrospective" and examine its rise and stagnation

  • taolson 11 hours ago
    Nice to see another language with Haskell / Miranda type syntax, but the vibe-coded implementation sure shows: e.g. src/Compiler/Infer.sky isUpperStart:

        isUpperStart : String -> Bool
        isUpperStart name =
            case String.slice 0 1 name of
                
                "A" ->
                    True
                
                "B" ->
                    True
                
                "C" ->
                    True
            ... for 23 more cases.
    
    And the corresponding go code in the bootstrap compiler is even worse.
    • bonesss 2 hours ago
      I started my career cleaning up systems written by solo devs in the pre internet era. I’ve seen a lot of starts_with_UCase() implementations like that.

      I see now I’m going to end my career cleaning up systems written by chronically online vibe coders, making all the same mistakes, with none of the excuses.

    • toastal 11 hours ago
      Haskell/Miranda use `::` instead of `:` for type signatures unlike Elm & basically the rest of the family which prioritize types being less keypresses than list cons.
      • taolson 11 hours ago
        Sorry, I meant "Haskell / Miranda style syntax" -- e.g. curried functions, concise syntax with little boilerplate, etc. The word type is too overloaded ;-)
  • zem 15 hours ago
    at first glance this looks amazing! basically provides everything I have ever wanted in a full stack language. looking forward to experimenting with it.

    edit: looking through the docs/examples some more, it looks like javascript interop is fairly clunky, both because it relies on string concatenation to embed fragments of javascript, and because the string concatenation syntax is not great (and the formatter makes it even worse - see the example at https://github.com/anzellai/sky/blob/main/examples/13-skysho...)

    I would encourage you to at the least add multiline strings with interpolation support, and ideally add a small compiler for html literals.

  • skybrian 14 hours ago
    Functional languages have some good and some bad features and there's no reason to copy them all. For example, you don't need to have a Hindley-Milner type system (bidirectional is better) or currying just because it's a functional language.
    • troupo 13 hours ago
      We need more pragmatic languages. E.g. Erlang and Elixir are functional, but eschew all the things FP purists advocate for (complex type systems, purity, currying by default etc.)
      • rapind 11 hours ago
        If you like Erlang, Elixir, and Elm/Haskell, then Gleam + Lustre (which is TEA) is a pretty great fit.
      • zem 12 hours ago
        ocaml has a complex type system but it's also very pragmatic in that it doesn't force you into any one paradigm, you can do whatever works best in a given situation. (scala arguably goes further in the "do whatever you want" direction but it also dials the complexity way up)
        • troupo 12 hours ago
          Yes! Completely forgot about OCaml because I only spent a couple of months with it
  • redoh 13 hours ago
    Elm's type system and architecture are genuinely pleasant to work with, so seeing those ideas ported to a Go compilation target is interesting. You get the safety and expressiveness of Elm but end up with a Go binary you can deploy anywhere. I wonder how the error messages compare, since that was always one of Elm's strongest features.
  • linzhangrun 5 hours ago
    It is a very good attempt, but I am quite pessimistic about the prospects of new programming languages in the AI era. Unless, of course, it is a language specifically designed for AI coding — for example, one that is self-contained and carries a great deal of contextual information, making it unsuitable for humans to write but highly suitable for large language models. That kind of future would probably be quite promising.
  • danpalmer 9 hours ago
    Wow, this is amazing. I always wanted to love Haskell but never really managed, Elm nailed the balance of usability and correctness, plus the architecture was beautiful.

    I've never liked Go, but its strengths are absolutely compiling to single binaries, fast compile times, and concurrency primitives (not necessarily using them) etc. Compiling to Go is a great idea.

  • librasteve 11 hours ago
    Very cool.

    I am comparing this https://github.com/anzellai/sky#tea-architecture with this https://harcstack.org (my thing) ... guess I have some work to do ;-)

  • submain 13 hours ago
    Great work :). Go doesn't have TCO. That means functional languages (no for loops) could blow up the stack. How did you solve that?
    • kubb 13 hours ago
      You can just compile any tail recursive function to a function with a loop and no recursion.
      • 1-more 12 hours ago
        This is in fact how Elm does it! Tail call recursion compiles to a while loop.
      • srean 11 hours ago
        That does not address the use case where I find tail recursion most tempting. That would be mutually recursive functions.

        If the function can be written as an idiomatic loop I probably would do so in the first place.

        • apgwoz 7 hours ago
          You _can_ do trampolines, but that is kind of infectious, or needs to be very explicit with extra code, etc.
      • adamwk 12 hours ago
        Right but recursion is only a smaller part of why the optimization is important. It means tail-called functions still build on the stack and long function chains—as is common with fp—can overflow
  • onlyrealcuzzo 12 hours ago
    First - awesome job. Congrats. Self hosting is an accomplishment!

    But I'm curious to get your thoughts on the process in hindsight.

    I understand why it's valuable: to cast a wide net in catching bugs and give a good signal that your language is generally "ready".

    I'm working on a similar language, but worried about going down the self-hosting path, as I think it'd slow me down rather than speed me up.

    How did it work for you?

    • ModernMech 11 hours ago
      What's the actual accomplishment here? It seems like the language came into existence a month ago and was written mostly by Claude. If self hosting is a matter of asking Claude to do it and it takes a couple weeks, is it really an accomplishment at all?
      • onlyrealcuzzo 11 hours ago
        Anything + Go's runtime is a reasonable language.

        Go's runtime is one of the greatest pieces of software ever built.

        Assuming this works - which self-hosting guarantees a minimum level of "working" - this is useful!

        I didn't want to rely on the unpredictability of a garbage collector, so I chose to build my own runtime, but it's not going to be as good as Go any time soon.

      • Philpax 8 hours ago
        "I could have made that!"

        "Yes, but you didn't."

      • troosevelt 11 hours ago
        Yes, somebody has to actually do it, and they did.
  • harikb 12 hours ago
    Somewhat unrelated to the language itself:

    > The compiler bootstraps through 3+ generations of self-compilation.

    I guess it applies to any language compiler, but f you are self-hosting, you will naturally release binary packages. Please make sure you have enough support behind the project to setup secure build pipeline. As a user, we will never be able to see something even one nesting-level up.

    • troad 8 hours ago
      I feel like there's too much of a fetish for self-hosting. There's this pernicious idea that a language isn't a 'real' language until it's self-hosted, but a self-hosted compiler imposes real costs in terms of portability, build integrity, etc.

      If I ever write a compiler - God forbid, because language design is exactly the kind of elegance bike-shedding I'll never crawl my way out of - it's going to be a straight-up C89 transpiler, with conditional asm inlines for optional modern features like SIMD. It would compile on anything and run on anything, for free, forever. Why would I ever give that up for some self-hosting social cachet?

      • p1necone 7 hours ago
        If you wrote the C89 outputting transpiler in your own language it would still be just as portable.
        • troad 4 hours ago
          I'd be dependent on pre-existing binaries that are closely wedded to a particular platform (OS, libc etc), and it over time it would become more and more difficult to attest to build integrity / ensure reproducible builds. (Is the ARM build meant to run an x64 emulator as part of some lengthy historic bootstrapping process?)
  • __natty__ 12 hours ago
    I would love to see Java inspired language compiled to Go. I really like Go portability and standard library and Java... verbosity. I prefer explicit names, types and all the syntax around that. Graalvm is not an answer for me because as far as I'm aware it doesn't support cross-compile.
    • weavie 10 hours ago
      You could make it happen in about a week and $50 worth of tokens.
  • riclib 15 hours ago
    Can’t wait to play with it. Great design!
  • tasuki 14 hours ago
    A bit too bleeding edge for me, but it does look super nice (ie exactly like Elm).
  • ch4s3 12 hours ago
    If you allow FFI are you really inspired by Elm? ;)
    • zem 8 hours ago
      they're inspired by repeating elm's good features and fixing the bad ones!
  • mrichman 12 hours ago
    Compiles to Go or transpiles to Go?
  • MegagramEnjoyer 5 hours ago
    wow this is pretty cool!
  • desireco42 9 hours ago
    Elm is a language I enjoyed the most. I love Ruby, I loved some other languages, even Haskell I enjoyed, but Elm is special. So let's make this work.

    Now that you got foundation created, let's see how to move it forward.