My new favourite thing is to use records to type interfaces for more C style libraries with lots of IO. The trick is to use Generic and a type class to gather the interface into a list or similar and running that in IO using the library. Say, using a record to type audio and midi inputs and outputs in an audio plugin.
Opus can do this correctly first try, you just need to give it the idea!
It gets it right after a few attempts.
The hard reality is none of them.
We will have some kind of type system/profs to help drive LLMs output, and those that still will have a job as system architects or whatever, will generate applications directly.
And just it happens with optimising compilers, there will be a way to generate some kind of intermediate representation, like the -S switch, but that is it.
Generating source code for 3 GL languages is an intermediate step.
Who thinks otherwise should spend sometime looking into papers of AI role in compiler development.
For example,
"CGO 2022 Keynote: Compiler 2.0"
https://www.youtube.com/watch?v=w_sX9aZoZxg
"Machine-Generated, Machine-Checked Proofs for a Verified Compiler"
Yes, and there's a good chance that will be Rust, at least in the short term.
You can't realistically write a whole program in Lean. So you want a good type system that combines well with a prover. Rust has a good type system, and annotating unsafe sections with proofs is becoming common practice in Rust. Right now you have to choose the proof syntax among several alternatives, but there are efforts to unify.
That's the future of Rust in many companies, agents or no: unsafe code must be annotated with proofs to eliminate undefined behavior.
Now certainly a purpose built system may be better than adding annotations to an existing language, but it'll probably work better if that happens after people & agents get experience writing the awkward combination.
I think we are on the Rewrite in Rust hype cycle now, eventually the dust will settle, when folks realise agents are an evolution of garbage collected systems.
I also explicitly stated that this was not likely the best way to do this.
Many folks not into Rust land will favour other tooling approaches for their LLMs, who knows might even be something based in Markdown or YAML, as these kind of things usually turn out.
Also, this doesn't necessarily mean there won't be any compilers either. It might just mean that the AI builds a dedicated compiler for each individual function.
Why a dedicated compiler for function? The whole infrastructure generates the code.
I suggest some sceptics to try to do a ecommerce like application only with low code agentic tools, that already gives a glimpse where we are going.
Get an headless ecommerce or CMS SaaS product like Alokai (https://alokai.com), an iPaaS agentic platform like Workato (https://www.workato.com), and the whole application logic will be diagrams with English prompts, naturally with guardrails to the IA infrastructure more or else inline with the desired behaviour.
That is all, that is the application, these lego pieces connected via prompts.
Be careful what you wish for, etc
Case in point: claude code is in the bun runtime of JS. Not in any fancy optimized binary
For instance
; Sysv native vectors. Initializer values require matching [].
(mut x (the v64 [10 20]))
(set x (+ x 5))
(at x 0 17)
(print (at x 1))
(print (all (= x (the v64 [17 25]))))
; Parameter and result types can be written inline
(fn add4 ((a w64) (b w64)) -> w64 (+ a b))
(let ((result (add4 (the w64 [1 2 3 4]) (the w64 [10 20 30 40]))))
(print (at result 3)))
You also get full fp primitives ; helpers reused below
(fn inc (x) (+ x 1))
(fn dbl (x) (* x 2))
(fn sq (x) (* x x))
(fn pair (a b) (+ a b))
(fn add3 (a b c) (+ a b c))
(fn dv (a b) (/ a b))
(fn id (x) x)
(fn zero (x) 0)
; |> : pipe a value left-to-right through functions.
(print (|> 5 inc dbl sq)) ; => 144 (sq(dbl(inc 5)))
; >> : left-to-right compose; << : right-to-left compose.
(print ((>> inc dbl) 5)) ; => 12 (dbl(inc 5))
(print ((<< dbl inc) 5)) ; => 12 (dbl(inc 5))
; fmap / <$> : apply f, then g (same as >>).
(print ((fmap inc dbl) 5)) ; => 12
(print ((<$> inc dbl) 5)) ; => 12 (11 on sysv: (inc (dbl 5)), function-first)
; <*> (and its alias <>) : the S combinator, (f x (g x)).
(print ((<*> + (lambda (x) (+ x 2))) 5)) ; => 12 (5 + (5+2))
; <&> : flipped fmap, a(b x). <**> : flipped S, (g x (f x)).
(print ((<&> inc dbl) 5)) ; => 11 (inc(dbl 5))
(print ((<**> (lambda (x) (+ x 2)) +) 5)) ; => 12 (5 + (5+2))