TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Austral: A systems language with linear types and capabilities

211 pointsby riidomover 2 years ago

28 comments

throwaway17_17over 2 years ago
This article, everything else aside, is excellent. I wrote a rambling bunch of stuff in this comment and before I posted I had to cut out a lot, because HN comments aren’t really the best place for an in depth discussion about type theory implementations. So, I’m just going to read the compiler source and then get a hold of you later.<p>I am really intrigued by your explicit anti-features list. They are very close to my preferences for language design, so I was going to keep on reading just from that. The feature list is spelled out well and I certainly think you managed to make this article a nice hook for looking further.<p>Then I followed a link to the language spec. My god, but is it not only written cleanly, but the presentation is so clean too. I got a short way in (after jumping to the type system specification) and stopped to come comment. I doubt you were expecting to get compliments for layout and formatting, but I am going to shamelessly steal your spec’s presentation for my language docs.
评论 #34198441 未加载
GuuDover 2 years ago
This is fantastically written documentation. What is even more exciting for me, that this is almost exactly what I was dreaming and talking non-stop about for the last few years. I never figured out the brilliant insight about redundancy of operator precedence. On the more embarrassing note in numerous implementation not-quite-attempts I always ended up gutting loops as a feature in favor of recursion and went with effects for capabilities (among other things). Then I was usually caught off guard by either of those or my other darling — partial application interacting in unexpected way (only for me probably) with linear types, which always punched me back to square one. Extremely impressed with how sound and grounded in reality your choices are. Fantastic job.
评论 #34196941 未加载
masklinnover 2 years ago
Seems interesting though I can not say that I like the Ada inheritance (especially the interface files, but the verbosity as well, the lack of tuples and verbosity of Pair seems like it would quickly be frustrating with a linear type system, as well as the seeming lack of same-scope shadowing).<p>Shame the examples are a bit too simplistic to show the value of linearity e.g.<p><pre><code> function closeFile(file: File): Unit; </code></pre> that&#x27;s the wrong interface, because closing a file can error. And it is an issue with destructors, which linear types can solve.<p>It would also demonstrate runtime error handling, which is completely ignored by the entire document and largely absent from the spec (error handling is discussed a lot, but never actually demonstrated).<p>The only document I found was <a href="https:&#x2F;&#x2F;austral-lang.org&#x2F;tutorial&#x2F;errors" rel="nofollow">https:&#x2F;&#x2F;austral-lang.org&#x2F;tutorial&#x2F;errors</a> which seems to indicate that not only does Austral (unfortunately imo) follows Haskell&#x27;s lead through using an Either for errors (which is clear as mud), it proceeds to break Haskell&#x27;s mnemonic for success&#x2F;failure (not that that&#x27;s great, but at least it was something).
评论 #34201217 未加载
atombenderover 2 years ago
I like this a lot! For several years I&#x27;ve been pondering the exact same idea of using linear types this way, combined with some kind of Rust-style borrowing. I&#x27;ve never really had any serious ambitions to create a programming language, though, so I&#x27;m happy to see someone finally doing this for real.<p>I love many of the choices here, like removing implicit type coercion, type inference, and operator precedence. I do worry that it could go too far. One thing we see with Go is that the simplicity of the language, while it has many virtues, also leads to some crude designs that feel regressive. For example, treating errors as values is a fine idea, but the language is too rudimentary to express sum types, so the handling of errors becomes crude and cluttered. Not bad enough to ruin the language, but bad enough to be an annoying wart. I hope that Austral can avoid falling into such traps when it needs to tackle more advanced concepts such as concurrency (I don&#x27;t know how this is done today?). Not having async&#x2F;await is fine, for example, provided that there is some other mechanism that doesn&#x27;t lead to spaghetti code or too much repetition.<p>The part I&#x27;m the least enthusiastic about is the Algol&#x2F;Ada-style syntax. I&#x27;m not sure the added verbosity of that syntax is superior to C-style syntax. The language I use the most these days, Go, is <i>essentially</i> Modula&#x2F;Oberon with C-style syntax and no semi colons, both of which I think improve the ergonomics.
评论 #34230696 未加载
skybrianover 2 years ago
It&#x27;s a good start. I expect that a lot will be learned by implementing the standard library, particularly if a serious attempt is made to make it work well on multiple platforms. Do you want to model a lot of platform-specific restrictions like Rust or sweep them under the rug like Go?<p>For example, real filesystems are complicated and quirky.<p>Though it&#x27;s risky to build on another experimental language, it seems like building on Zig&#x27;s toolchain would be a good way to get lots of cross-platform capability and experience quickly, since it accepts C and generates code for many platforms.
评论 #34201830 未加载
ummonkover 2 years ago
Simple spec? Check. Linear type memory management? Check. Ada syntax? Check. Avoiding footguns? Check. It&#x27;s like you took my fantasy of the ideal low level programming language that I&#x27;ve never gotten around to implementing, and you actually built it.
quantifiedover 2 years ago
This is rather interesting. Safe and reliable programming in the large is an important goal. Generics, sum types and typeclasses make different kinds of useful abstraction available from the get-go. I&#x27;m looking forward to progress on this.
评论 #34196776 未加载
college_physicsover 2 years ago
Can somebody explain what is &quot;linear&quot; about linear types. There seems to be a common pattern in computer science of reusing well established mathematical terms (e.g. vectors, tensors) in confusing ways.
评论 #34197102 未加载
评论 #34196742 未加载
评论 #34196731 未加载
评论 #34322502 未加载
评论 #34196772 未加载
评论 #34197303 未加载
评论 #34196761 未加载
评论 #34200475 未加载
quagover 2 years ago
How does closeFile get implemented? That is, how do you consume a linear type without having to either pass it to another function or return it?<p>Does every linear value ultimately have to be passed to an extern function that doesn’t follow the linear typing rules?
评论 #34200833 未加载
评论 #34220903 未加载
valenterryover 2 years ago
Looks promising!<p>Two nitpicks from my side.<p>From the anti-goals:<p>&gt; Async is a very specific feature, and every way of doing concurrency other than kernel threads has come and gone out of fashion (think Scala actors and Goroutines, two very admirable features)<p>Scala actors are not a language feature so are not remotely comparable to async&#x2F;await or Goroutines. They are also not &quot;out of fashion&quot;, if anything they were just overused - but it doesn&#x27;t impact the language in any way at all.<p>&gt; no context-sensitive syntax<p>There are different opinions on language design and that&#x27;s fine. But &quot;ease of use&quot; and &quot;complex systems&quot; are not at adds. In fact, you can argue that Assembly is a &quot;simpler&quot; system than Austral. But does that make it easier to use? I don&#x27;t think so. I think this part sheds light on the fact that the author needs to work on that part - not necessarily on changing the language design, but at least the language isn&#x27;t great.
epageover 2 years ago
Interesting ideas but I&#x27;m in the camp that having everything be explicit causes complexity to be foisted on the user. There are times and places where that simplicity might offer some advantages but I&#x27;d rather my systems language scale between contexts.
评论 #34200420 未加载
评论 #34198850 未加载
评论 #34199272 未加载
JonChesterfieldover 2 years ago
What does&#x2F;will Austral do on out of stack memory? Assuming it maps tail calls to branches, the call stack still grows on the non-tail calls.<p>Options I&#x27;m aware of are die (optionally gracefully), allocate more stack (segments or moving), allocate a lot of address space up front and then die on exhaustion.<p>Asking because I think there&#x27;s a reasonable argument that out of heap and out of stack are the same category, and the docs discuss returning optional from allocating functions, but not tagging all functions with an optional to indicate out of stack.
agentultraover 2 years ago
Cool idea, dramatic writing. I can deal with linear types without the hand-wringing.<p>As someone famous in CS once said, “simplicity is a great virtue but it takes hard work to achieve it and education to appreciate it.”<p>Let’s face it: programming is hard and no amount of waving our hands and refusing to learn anything new is going to make anything better.<p>If this linear type system is great, skip to why it’s great.<p>Again, a lot of neat ideas in here. The parser is a good idea. Langsec and a security focused language is nice to see!
zozbot234over 2 years ago
Nice writeup. I think Rust will also get true linear types at some point (i.e. types that can&#x27;t be auto-dropped) because they&#x27;re required for improved async support. One key obstacle to this is that Rust supports panics anywhere-- there&#x27;s no provision for &quot;panic-free&quot; code as of yet-- and a panic might need to drop values as part of unwinding the stack. The author is surely aware of this, but it&#x27;s worth making it clear.
评论 #34197386 未加载
renoxover 2 years ago
A very interesting language, a few remarks:<p>- your blog &quot;hides&quot; the links behind barely visible font changes, quite funny for someone who designed a programming language with no hidden function call.. Don&#x27;t do this please.<p>- the &quot;Arithmetic Expression&quot; section talk about integer division overflows but not about the other overflows?<p>- I couldn&#x27;t understand the &quot;Cast Expression&quot; section, either it&#x27;s me or it has to be clarified.. Also a syntax remark: I&#x27;m surprised that there is no easily greppable keyword for casting.<p>- two other comments about syntax:<p>1) the &#x27;!&#x27; symbol is used to dereference and in &quot;read-write borrow&quot;, I don&#x27;t see any obvious relationship between both usage, maybe you could use &#x27;@&#x27; for dereference ?<p>2) how about using &lt;&gt; for not equal insteal of &#x2F;= ? The &quot;C programmer I am&quot; read &quot;a &#x2F;= b;&quot; as &quot;a = a &#x2F; b;&quot; ..
GMoromisatoover 2 years ago
Instead of linear types, would it be possible to just enforce some kind of &quot;must call close&quot; policy?<p>What if you somehow mark the close() function as--let me make up a name--a &quot;destructor&quot;. Then enforce at compile time that a value must always have a call to a destructor (or maybe it gets called automatically when out of scope).<p>1. Does that solve the close problem as well as linear types?<p>2. Do linear types solve other problems that the above doesn&#x27;t?
评论 #34198614 未加载
评论 #34200928 未加载
zetalyraeover 2 years ago
Author here. Happy to answer questions.
评论 #34197607 未加载
评论 #34198153 未加载
评论 #34205889 未加载
tinyspacewizardover 2 years ago
I have some questions; hope the OP is still around!<p>Will there be partial application?<p><pre><code> let appendHelloFile = appendFile(&quot;Hello&quot;); let f = openFile(&quot;log.txt&quot;); let f2 = appendHelloFile(f); closeFile(f2); </code></pre> I suppose this might complicate the linear type system?<p>Will there be a pipeline operator? I think this fits really nicely with linear types:<p><pre><code> openFile(&quot;log.txt&quot;) |&gt; appendFile(&quot;Hello&quot;) |&gt; closeFile </code></pre> This may be at odds with the no operator precedence rule.<p>You say that async will not be baked into the langauge. I think this is the right decision. However, will there be a syntatic sugar that can be used to avoid the &quot;pyramid of doom&quot; when writing promise-orientated code? It is possible to make this general purpose if done right.
choegerover 2 years ago
Interesting design. I agree 99% with the choices. My only disagreement would be about not being able to overload binary operators. I wonder how the type system handles the inherent overloading of * for floats and integers. Besides this minor point, I totally agree with the design and intent!
eikenberryover 2 years ago
&gt; every way of doing concurrency other than kernel threads has come and gone out of fashion (think Scala actors and Goroutines, two very admirable features).<p>I&#x27;d say the fact that these examples are around show that NxM, green-over-kernel threading works and works well. It made it through the crucible of fashion and is now a &quot;good&quot; way. Much like GC did. So I&#x27;d say your claim that kernel threads are it is misplaced... unless you just consider NxM threads to be kernel threads w&#x2F; some sugar?
zrkrlcover 2 years ago
I love this! I&#x27;m currently reading the entire spec as I&#x27;m writing this<p>BTW, you have a typo in one of your examples.<p>&gt; import (<p>&gt; ...,<p>&gt; Relase_Filesystem,<p>&gt; ...<p>&gt; )
silasdbover 2 years ago
Hi. Thanks for the great work and great write up!<p>At a first glance, I only see advantages with this approach. What would be the caveats of using Austral instead of Rust (disregarding the ecosystem and toolchain factors)?
Kinranyover 2 years ago
&gt; Anti-features: macros<p>Is there a different mechanism for compile-time programming?
评论 #34202149 未加载
docandrewover 2 years ago
This is very close to the language I’ve been dreaming of! Best wishes for its success.
asplakeover 2 years ago
Is the type&#x2F;kind Region defined anywhere?
评论 #34197440 未加载
vlovich123over 2 years ago
Interesting observation that contradicts my experience:<p>&gt; A common misconception is that checking for allocation failure is pointless, since a program might be terminated by the OS if memory is exhausted, or because platforms that implement memory overcommit (such as Linux) will always return a pointer as though allocation had succeeded, and crash when writing to that pointer. This is a misconception for the following reasons:<p>&gt; Memory overcommit on Linux can be turned off.<p>&gt; Linux is not the only platform.<p>&gt; Memory exhaustion is not the only situation where allocation might fail: if memory is sufficiently fragmented that a chunk of the requested size is not available, allocation will fail.<p>This is kind of the eternal vim vs eMacs debate but for malloc. In practice, I’ve not found this philosophy to be useful and actually problematic and the reasons given are the “easy” ones to convince more junior engineers. They’re true btw and the counter points provided aren’t really convincing. Regardless, the real reasons are:<p>* Memory allocation failures happen infrequently in practice.<p>* No one writes tests that simulate behavior of code under allocation failures.<p>* Memory allocation failures are basically treated as contract violations anyway in terms of triage - it’s not different from any other bug and you’d still need to fix it.<p>Crashing on a memory allocation failure:<p>* there’s no untested error recovery code to worry about<p>* the cause of the malloc failure means something else is broken &#x2F; misconfigured. A crash tells you what to fix &#x2F; when to fix it. A silent recovery attempt (when successful) will mask this and shift the problem (eg bug in error handling later or something)<p>There are times when you allocate memory and <i>could</i> handle failure gracefully by rejecting the request or something. However, as I mentioned. Memory allocation failures are rare and when they happen you need to fix a bug anyway. So crashing on a rare condition instead of running untested error recovery code is probably preferable in general.<p>Context: I have experience in mobile, embedded, desktop, and cloud so I’ve seen the gamut of dev environments. And everywhere the “abandon on malloc failure” turns out to be a more maintainable strategy that results in more robust code that’s simpler and shorter and faster&#x2F;cheaper to develop because you’re not writing and thinking about error handling paths that never get run.<p>Regardless, it is kind of interesting to see a language adopt this philosophy. Maybe that can address some of the problems of trying to do this manually in other languages. I’m skeptical because the error paths problem remains, but I’m open to the experiment
评论 #34203592 未加载
评论 #34201575 未加载
array_bullockover 2 years ago
why aren&#x27;t linear types called acyclic types?
评论 #34334952 未加载
still_grokkingover 2 years ago
The language was trivial to break in a few minutes. (And it likely can&#x27;t do anything about it [edit to make this clear: This is not an implementation bug. Without depended types or abstract interpretation this is unfixable¹, as I see it]).<p><pre><code> module body Test is function recur(n: Nat64): Nat64 is if n &lt; 2 then return n; else return recur(n - 1); end if; end; function main(): ExitCode is print(&quot;recur(50000000) = &quot;); printLn(recur(50000000)); return ExitSuccess(); end; end module body. </code></pre> This code generates almost 3.5 kLOC of C which results in a segmentation fault when compiled and run on my machine.<p>I&#x27;m not impressed to be honest.<p>I would be less harsh if this wouldn&#x27;t be advertised as sane and safe language. But it is.<p>---<p>¹ Of course you could fix this with for example trampolining. But than the promise of &quot;no hidden control flow or functions calls or allocations&quot; would be broken instantly.
评论 #34203568 未加载
评论 #34203950 未加载