[HN Gopher] Loon: A functional lang with invisible types, safe o...
       ___________________________________________________________________
        
       Loon: A functional lang with invisible types, safe ownership, and
       alg. effects
        
       Author : surprisetalk
       Score  : 71 points
       Date   : 2026-02-20 21:45 UTC (1 days ago)
        
 (HTM) web link (loonlang.com)
 (TXT) w3m dump (loonlang.com)
        
       | phpnode wrote:
       | The pattern matching example has a type Shape which is never
       | referenced and this seems to conflict with the idea that you
       | never write a type, am I missing something obvious?
        
         | KPGv2 wrote:
         | I think they mean you never write types for your variables or
         | functions. They don't mean you can't create types. That's the
         | reference to Hindley-Milner type system and type inference. You
         | don't have to say
         | 
         | x : Nat x = 5
         | 
         | You just say x = 5
         | 
         | I personally don't like that you don't seem to be able to
         | manually describe the type for a fn/var, because it's very
         | useful when prototyping to write stubs where you provide the
         | typedef but then the actual variable/function is just marked as
         | "todo"
        
       | weitendorf wrote:
       | Very cool! I've been flirting with the idea of biting the bullet
       | and moving more towards language extensions around protobuf/grpc
       | vs just tools so it's really great to see projects on the other
       | side of that kind of decision shipping and what choices they made
       | 
       | Why the square brackets in particular? Notation is such an
       | annoying part of this stuff, I'm actually leaning towards pushing
       | a lot of structure to the filesystem
        
       | luckymate wrote:
       | I think I am in love. Clojure + Rust, everything is typed, but I
       | don't need to annotate. And algebraic effects that I really
       | wanted to explore in Ocaml, but now can do it in language with
       | way easier syntax. I might be missing bit of Clojure dynamic
       | nature, but it looks like a bunch of really interesting ideas in
       | one language.
        
         | christophilus wrote:
         | Yeah. Clojure is by far my favorite dynamic language. But, I
         | love static types. At a glance, a quick glance at Loon- looks
         | like it could just flat out become my favorite language. Loon
         | with a standard library that approaches Go's would be
         | :chefskiss:
        
         | drob518 wrote:
         | Coming from Clojure, I like types being invisible. Square
         | brackets feels like a needless change. If you want sexprs, just
         | use sexprs. Interesting ideas, as you say.
        
         | ecto wrote:
         | <3
        
       | xigoi wrote:
       | Looks great! However, the website is really slow. Every page
       | takes several seconds to load and trying to open the reference
       | freezes my browser.
        
         | ethmarks wrote:
         | Apparently the site itself is written in Loon. The HTML is just
         | a static shell that loads a `boot.js` script[1] that runs some
         | WASM that compiles and evals the Loon source files. I found the
         | source code here[2].
         | 
         | Definitely cool in concept, but very performance-intensive and
         | slow.
         | 
         | [1]: https://loonlang.com/boot.js
         | 
         | [2]: https://github.com/ecto/loon/tree/main/web
        
         | mapcars wrote:
         | I'm assuming the website is written in Loon and according to
         | roadmap its version 0.4 and compilation is planned in 0.7. So
         | it demonstrates that the language works, but its not optimised
         | yet.
        
           | ecto wrote:
           | exactly! I didn't post this (thank u whoever did though) so
           | wasn't ready to launch yet. but the idea is it will SSR and
           | hydrate each page. I want to pull it all out into a framework
           | congruent to Next.js
        
       | davidee wrote:
       | Perhaps relevant: https://campedersen.com/loon
       | 
       | This looks like a really neat project/idea; seeing the road map
       | is exciting too, nearly everything I'd want.
       | 
       | I don't love the brackets syntax, or the [op val1 val2] ([* x x])
       | style, but I appreciate the attempt at clarity and consistency
       | and none of these things are dealbreakers.
       | 
       | I do wonder why they've leaned so hard into talking about the
       | type system being out of sight. Again, not a dealbreaker, but I
       | feel strongly that explicit typing has a place in codebases
       | beyond "describe something because you have to".
       | 
       | Strongly typed languages strike me as providing detailed hints
       | throughout the codebase about what "shape" I need my data in or
       | what shape of data I'm dealing with (without needing to lean on
       | an LSP). I find it makes things very readable, almost self-
       | documenting when done right.
       | 
       | From their docs about their choices: "The reasoning is simple:
       | types exist to help the compiler catch your mistakes. They do not
       | exist to help you express intent, at least not primarily." This
       | strikes me as unnecessarily pedantic; as someone reading more
       | code than I write (even my own), seeing a type distinctly--
       | particular as part of a function signature--helps me understand
       | (or add strong context) to the original author's goal before I
       | even get to reading the implementation.
       | 
       | I find this doubly so when working through monadic types where I
       | may get a typed error, a value, and have it all wrapped in an
       | async promise of some kind (or perhaps an effect or two).
       | 
       | By the same token many languages allow you to leave out type
       | annotations where they may be simple or clearly implied (and/or
       | inferred by the compiler), so again, I'm not understanding the
       | PoV (or need) for these claims. Perhaps Loon simply does it
       | better? Am I missing something? Can I write return types to stub
       | functions?
       | 
       | From the above blog post: "That's how good type inference feels!
       | You write code. The types are just there. Because the language
       | can see where it's going." Again, it feels strongly geared
       | towards a world where we value writing code over
       | reading/maintaining/understanding code, but maybe that's just my
       | own bias/limitations.
       | 
       | Will follow it closely.
        
         | wk_end wrote:
         | Yeah, the idea that types exist just to help the compiler catch
         | your mistakes shows a depressingly superficial understanding of
         | the benefits of static typing.
         | 
         | Types exist so that the compiler can reason about your code
         | better - but not incidentally, they also help _you_ reason
         | about your code better!
         | 
         | To wit: even when working in dynamic languages, it's often
         | considered a good practice to write down in docstrings the
         | types of objects a function can operate on, even without static
         | enforcement. Thinking about types is helpful for humans, too.
         | 
         | And it's not even just a thing to help you read code in the
         | future - types help me _write_ code, because as I sit down to
         | write a function I know the possible values and states and
         | capabilities of the object I 'm working with. In the best of
         | cases I can analytically handle all the possible cases of the
         | object, almost automatically - the code flows out of the
         | structure of the type.
        
           | bossyTeacher wrote:
           | > Types exist so that the compiler can reason about your code
           | better - but not incidentally, they also help you reason
           | about your code better!
           | 
           | THIS. So much. This observation is extremely intuitive to me.
        
         | cptroot wrote:
         | Good news, there's a line in the "Coming from Rust"[1] page
         | that says
         | 
         | > You never annotate a function signature unless you want to
         | for documentation purposes.
         | 
         | so it sounds like function annotation is still an option for
         | the purposes of communication, just no longer required in all
         | cases.
         | 
         | [1] https://loonlang.com/concepts/from-rust
        
           | cptroot wrote:
           | Aha, here's the syntax in case you're curious (using an
           | example lifted from the playground)                 [type
           | Shape         [Circle f64]         [Rect f64 f64]
           | Point       ]            [sig test_sig : Shape -> Float]
           | [fn test_sig [shape]         [match shape           [Circle
           | r] [* 3.14159 [* r r]]           [Rect w h] [* w h]
           | Point 0.0         ]       ]
           | 
           | Unfortunately it seems like this doesn't currently work as
           | expected when I use it in the playground, so I'm going to go
           | file an issue
        
             | ecto wrote:
             | thank you <3 I will fix asap
        
         | mapcars wrote:
         | > Strongly typed languages strike me as providing detailed
         | hints throughout the codebase about what "shape" I need my data
         | in
         | 
         | I agree that seeing types is helpful, though typing them is
         | also not necessary. Perhaps the solution is an IDE that shows
         | you all the types inferred by the compiler or maybe a linter
         | that adds comments with types on file save.
        
           | zokier wrote:
           | > I agree that seeing types is helpful, though typing them is
           | also not necessary. Perhaps the solution is an IDE that shows
           | you all the types inferred by the compiler
           | 
           | see "The Editor as Type Viewer" section in the docs:
           | https://loonlang.com/concepts/invisible-types
        
       | cptroot wrote:
       | Neat! I think the website could use a bit more information about
       | how the "global" Effect handlers work, and whether it's possible
       | to opt-in to that functionality yourself when writing Effects.
       | 
       | That being said I took a look at the roadmap and the next major
       | release is the one that focuses on Effects, so perhaps I'm
       | jumping the gun a tad. Maybe I'll whip this out for AoC this
       | year!
        
       | dxdm wrote:
       | > Square brackets replace parentheses for a clean, uniform
       | syntax.
       | 
       | Oh dear, why? Abrasive aesthetics aside, this is bad for people
       | with certain non-English keyboard layouts. Not me, but many do
       | exist.
        
         | IshKebab wrote:
         | Better for people _with_ English keyboards though. And I prefer
         | the aesthetics.
        
           | Dansvidania wrote:
           | Is it better for English keyboards because () are shifted and
           | [] are not ?
        
           | dxdm wrote:
           | Point taken. I forgot that brackets are not shifted on my
           | keyboard.
           | 
           | They do require worse acrobatics than a shift key on a German
           | keyboard, though - one of the Alt keys is special and needed
           | to trigger them, if memory serves.
           | 
           | Well, that's another argument for everyone to use an English
           | layout for coding, I suppose.
        
       | mintplant wrote:
       | I got really excited reading this! The docs site is very polished
       | and hypes up lots of features which click with things I've been
       | wanting out of a language. But then I went to the repository [0]
       | and realized that this is a week-old project, with every single
       | commit written by Claude. I went to the playground page [1] and
       | tried the example for effects, a headline feature and what drew
       | me in the most, but it threw an "unbound symbol" error. I thought
       | maybe the example could just be out-of-date, so I tried the
       | example under the "Algebraic effects" heading on the homepage,
       | which shows a different syntax, but that threw a parse error. The
       | "Pattern matching" example is supposed to return 78.5, but it
       | returns 15.700000000000001 when run in the playground. The
       | example for "Mutation" on the ownership docs page [2] throws
       | "unbound symbol 'set!'". The "Type Signatures" example from the
       | types guide [3] throws another parse error. That's where I
       | stopped.
       | 
       | How much of this is actually real?
       | 
       | [0] https://github.com/ecto/loon
       | 
       | [1] https://loonlang.com/play
       | 
       | [2] https://loonlang.com/guide/ownership
       | 
       | [3] https://loonlang.com/guide/types
        
         | ecto wrote:
         | hey thank you, should all be fixed now!
        
           | drob518 wrote:
           | Yea, kudos on the docs. It's rare that something this new is
           | this polished. Well done!
        
       | IshKebab wrote:
       | It's such a lot of effort to make a language like this. I don't
       | get why they don't just put in like 2% more effort and add syntax
       | that makes it less awful for humans. Nobody _really_ wants to
       | write `[* 5 5]` do they?                 [fn square [x] [* x x]]
       | 
       | Could very easily be                 fn square(x) = x * x;
       | 
       | Or something like that, which is _much_ more readable.
       | 
       | Also
       | 
       | > Hindley-Milner inference eliminates type annotations.
       | 
       | I think it's pretty widely agreed at this point that _global_
       | type inference is a bad idea. The downsides outweigh the upsides.
       | Specifically: much worse errors  & much less readable code.
        
         | mapcars wrote:
         | You never used lisp-like languages did you?
        
           | IshKebab wrote:
           | No because the syntax is so awful. Programming languages are
           | consumed by machines but written by humans. You need to find
           | a middle ground that works for both. That's (one of the
           | reasons) why we don't all program in assembly any more.
           | 
           | Lisp and similar are just "hey it's really easy to write a
           | parser if we just make all programmers write the AST
           | directly!". Cool if the goal of your language is a really
           | simple parser. Not so cool if you want to make it pleasant to
           | read for humans.
        
       | pmcgoron wrote:
       | 1. I don't know much about HM systems mathematically, but how do
       | the effect handlers interact with type inference? I thought there
       | was some issues with automatic inference there.
       | 
       | 2. The macros examples on the website don't show binding
       | situations. Are the macro hygienic like in Scheme?
       | 
       | 3. Why the choice of [] over ()?
        
         | ecto wrote:
         | good questions
         | 
         | 1. effects are tracked in the type system as row types, so they
         | compose with HM inference pretty naturally. the tricky part is
         | effect polymorphism. Loon handles that similarly to how koka
         | does it, with row polymorphism. no ambiguity issues so far but
         | idk
         | 
         | 2. yes, macros are hygienic! documenting some binding
         | situations would make a great first PR :)
         | 
         | 3. easier to type!
        
       | kronnpp wrote:
       | How is it related to the Standard Meta Language (SML) family of
       | languages?
        
       | rivetfasten wrote:
       | This looks really nice! I'm excited to see it and am left with
       | questions from perusing the site. Let me know if I missed it.
       | 
       | It's simple and also has an excellent choice of where to invest
       | in powerful features. It looks like an elegant, minimal selection
       | of things existing languages already do well, while cutting out a
       | lot of cruft.
       | 
       | The site also mentions two differentiating and less established
       | features that make it sound like more than yet another fp remix:
       | type-based ownership and algebraic effects.
       | 
       | While ownership stuff is well explored by Rust and a less
       | explicit variation by Mojo, this sounds like a meaningful
       | innovation and deserves a good write-up! Ownership is an
       | execution-centric idea, where fp usually tries to stay
       | evaluation-centric (Turing v Church). It's hard to make these
       | ideas work will together, and real progress is exciting.
       | 
       | I'm less familiar with algebraic effects, but it seems like a
       | somewhat newer (in the broader consciousness) idea with a lot of
       | variation. How does Loon approach it?
       | 
       | These seem like the killer features, and I'd love to see more
       | details.
       | 
       | (The one technical choice I just can't agree with is multi-arity
       | definitions. They make writing code easier and reading it harder,
       | which is rarely or never the better choice. Teams discourage
       | function overloading all the time for this reason.)
       | 
       | Thanks for sharing!
        
         | ecto wrote:
         | thanks for the kind words :)
         | 
         | You're right, ownership and effects are the real
         | differentiators. The idea here is to let the compiler discover
         | ownership rather than it being declared imperatively
         | 
         | Regarding algebraic effects, Loon uses continuations similar to
         | Koka but more restrictive. Effects are declared with
         | operations, and every side effect (IO, failure, async, state)
         | is an effect that propagates through the call graph. The
         | interesting part is `handle`, which lets you intercept effects:
         | [handle [load-config "app.toml"]         [IO.read-file path]
         | [resume "mock contents"]         [Fail.fail msg]     "default"]
         | 
         | Handling an effect subtracts it from the function's effect
         | setso a function that handles all its IO internally is pure
         | from the outside. This replaces exceptions, async/await, DI,
         | and mocking with one mechanism. Testing is just handling
         | effects with test data
         | 
         | Multi-arity: get lost! fork me?
        
       | netbioserror wrote:
       | True beauty. Wow. My only ask would be optional type annotations
       | for function and type parameters, so it's easy to fully describe
       | your interfaces in code.
        
       | leke wrote:
       | This reminds me a lot of REBOL
        
       | skybrian wrote:
       | Not for me. Type annotations at API boundaries and bidirectional
       | type checking is better. I don't know why people keep thinking
       | Hindley-Milner is good.
        
       ___________________________________________________________________
       (page generated 2026-02-21 23:00 UTC)