Hello, author here! As the website says, the compiler itself is still in a very early state where basic things like functions, types, traits, inference, monomorphisation, and codegen are implemented. The fun stuff of algebraic effects, lifetime inference, and refinement types are not however. Though I can elaborate on implementation strategies of these for anyone curious. For example, algebraic effects in existing languages can be quite slow at runtime due to the use of continuations, the translation to a monad stack, and/or dynamically finding handlers at runtime. It is my plan to monomorphise them away and inline all these cases as in the following paper (1). With this, handlers are inlined into functions, continuations are normal closures, and continuations that aren't called multiple times are inlined.
I'd really like to find "the low-level functional language" without "the fun stuff". Or at least it should have simple and boring subset that is usable without "the fun stuff".
Something like Caml Light - precursor to Ocaml - but with translation to C instead of bytecode, so it will be fast and will have comfortable integration with C libraries.
This is definitely an interesting thought. My thinking is that "the fun stuff" tends to help make the language more functional, so removing it you are left with a more imperative language resembling a C clone with traits and type inference. Then if you want easier C interop you must remove traits and either remove modules as well or provide a standard method of mangling module names into function names. At that point I think you may as well use an existing "better C" language like Odin, Zig, Jai, C3, etc.
My definition of low level is no tracing GC, values are unboxed by default, and users still have control to do low level things (raw pointers, other unsafe operations) when needed, even if it is not the default.
This is a very deep and mature assessment. I have high expectations for the future of Ante. Higher than Rust, in particular, provided it supports some analog of destructors.
The generally accepted definition of a low level language is a language that provides little or no abstraction from a computer's instruction set architecture. In actuality, C is a lower level functional programming language than Ante, because C functions are first-class citizens.
I like the lack of GC! What is the method for always incremental compilation? The benefits are obvious, but isn't it problematic to have two authoritative representations of the same source? It would be fantastic if you get that to work well!
Fwiw C is actually a huge abstraction over modern hardware.
It's a good representation of the PDP-11 and similar-era computers. It's also a good abstraction for modern microcontrollers.
C's view of the world is also a really poor fit for today's larger CPUs. Your computer has to jump through a ton of hoops to make itself seem C-like. C has no concept of vectorization, speculative execution, branch prediction, multiple cores, caches, MMUs, etc.
For basically any desktop/laptop/smartphone CPU, the C runtime is more like a little VM than an accurate model of the hardware underneath.
How would you expose speculative execution & branch prediction? Cache behaviour is well understood so what's wrong with it? What would you do to expose MMUs to the programmer, and what would they do with it/how would it help?
[1] but aren't there libraries that expose it just fine in a portable way?
So what are the $%^&* semantics we're supposed to build into the language to avoid the need for speculation via OOO exec and branch prediction. Because as a guy interested in languages you might have something to teach me, assuming you have any idea what you're talking about.
Eh, isn't it a bit of a stretch to claim you can program functionally in C? You can mimic it, but without easy closures you can't follow _any_ functional programming patterns that are built on composing functions into new ones in expressions (e.g. binding the operation argument to a fold)
C is great, and it would be cool to see something that is similarly close to the instruction set but has functions as values
A functional programming language is a programming language in which functions are first class citizens. C is such a language.
Of course there are many programming patterns that are in more acceptable functional programming languages than C. Whether a programming language is considered functional is not the same as which patterns are supported in the language.
Your idea of what FP means is completely nonstandard.
For the record, there is not one accepted definition, but we can get close by saying that FP languages are those based on lambda calculus as their semantics core. And the primary mechanism in lambda calculus is variable capture (as done in closures).
C is based on the Von-Neumann model and has absolutely nothing to do with the lambda calculus. No reasonable PL expert considers it functional.
There's a lovely Perlisism for this: "A programming language is low level when its programs require attention to the irrelevant." Which is interesting in this context because it's clearly not a good fit for Ante, where it looks like many traditional features of "low-level" languages no longer require such attention! So maybe it's not Perlis-low-level; maybe it's "machine-oriented"?
> fun stuff of algebraic effects, lifetime inference, and refinement types
> I'd really like to find "the low-level functional language" without "the fun stuff"
But current stable Ocaml has neither of the "fun stuff" mentioned and compiles to native code. So isn't that exactly what you want?
It doesn't even need lifetime analysis because automatic garbage collection be praised.
And algebraic effects are awesome. Sure they are not mainstream yet but conceptional there is a strong parallel to the Common Lisp condition system which is quite established. Not sure why you wouldn't want to have them. Also it is still a long way until we will see them used in user facing stuff in Ocaml.
Ocaml doesn't compile to C. Sometimes having translated C source is major gain.
I'm not Ocaml implementation expert, but I suppose Ocaml exception handling and garbage collector could be tricky to aware about when one extend or embed Ocaml.
To be honestly, my fellow did Ocaml embedding once. He made able to load natively-compiled plugins written in Ocaml into C based software. And it worked. I didn't dig into details, though. There was at least one bug regarding garbage collection (and it happens that I fixed it).
`ocaml-ctypes` currently supports "reverse-bindings" (making OCaml functions available from C) out-of-the-box and mostly takes care of the intersection you are talking about, so this already works quite well.
The only gain from emiting C code is portability to weird architecture that would be covered by C compilers but not the OCaml one; which is arguably a pretty niche use-case.
For functional lang transpiling to C, you can look at Fennel - a Clojure dialect over C. However, if you want functional and statically typed, then you are probably out of luck.
This was basically my motivation when I designed the language I use for my day-to-day tasks where I program. I just wanted a ‘functional’ sort-of language that compiled to C.
Even though I’ll never release it, it was a rewarding theoretical and practical exercise.
As an aside, I really love how detailed and example-ful Ante’s site is. It looks like a ‘fun’ language and I hope the creator keeps working on it.
I strongly doubt that, most people would look at it and say it was a concatenative language (it’s not, but that is a semantics issue) and immediate disregard. The language, while being a modal dependently typed language, there is no mandatory ‘safety’ features and memory is largely manually managed. And after the blowback, complaints, and negativity posts about Hare on HN, I just don’t care to argue the fact that my language exists.
There is a group of programming language enthusiasts that would be interested in all sorts of languages.
Then there are people who will criticize just about anything for the sake of doing it. Just ignore those people and make a day more interesting for the people who share your passions.
That is the argument that has been made by my few friends who are interested in PLT as well. The other option I’ve considered if starting a blog or similar (although my son keeps suggesting a YouTube channel) and doing a longer series of posts concerning the language, type theory, and category theory inspirations present in the semantics of the language.
I would love to imagine I could be the next Andrew Kelly (creator of Zig), I don’t know that I can actually be a language founder.
I get it that programming languages are quite different from most of other projects in that normal projects can have a small user base and still be considered a success in solving a given problem, but with programming languages the mere fear of not being able to reach a sizeable community is enough to not even try out a new approach.
Nevertheless I think there is space for experimental/research languages. Just don't burden yourself thinking in terms of "this is the next great thing" and it will be fun, and perhaps your work and the ideas underlying it will even leave a mark, even if that doesn't necessarily mean that the particular incarnation of that particular language will ever reach adoption.
We not only stand on the shoulder of giants. We all stand on the shoulders of billions of dwarfs.
C can sometimes be an easier target since you don't have to learn LLVM's API.
C is also more portable than llvm since there is a greater variety of C compilers for a greater variety of architectures than llvm targets.
The dot product example gave me pause because map2 seems to be the same as zipWith. Does that exist in Ante? Without context I might have thought map2 was going to act as bimap. Take that for what you think it's worth :)
Also I might be having a brain fart -- but isn't the dot product in your example equal to 32?
map2 is indeed another name for zipWith. I believe I got that name from Racket if memory serves. Compared to zipWith I like its symmetry with the 1 argument map. I also wasn't aware of bimap! I can't seem to find a function of that name online, though I did find the BiMap haskell package, is that what you're referring to?
And yes, the dot product should be 32, thank you :)
I was wondering why the dot product wasn't 32! Good thing I checked. Also this seems like a cool new language, I need to learn a functional language, I wonder how far this language will go in development.
I calculated the dot product in my head because it looked off. Then I calculated it in my computer. Then I came to the comment section before losing all confidence in what I thought was a dot product of two vectors.
Very neat project! I noticed that Ante doesn’t have explicit region type declarations. As I recall, existing algorithms implemented for ML can sometimes infer very large regions which causes memory usage to balloon. It looks like smart pointers are part of the plan to address that possibility, but I’d love to hear more about your thoughts on memory management.
Correct, a key goal is to have no explicit region/lifetime annotations. There have been several papers on region inference after the originals by Tofte & Taplin, all attempting to refine the original analysis by inferring shorter lifetimes. First by analyzing when a region can be safely emptied and re-used, then by abandoning the stack discipline, etc. Unfortunately, none of these are viable in a real program in my opinion. Although they each infer shorter lifetimes in a few cases the core problem of "collections will unify the lifetime variables of all elements in the collection" and "branching on a value and conditionally returning it extends its lifetime, even if the branch was not taken" remain unsolved.
An ideal solution to me needs to solve these problems. Since there is already a large body of research trying to address this on the static side and failing, I believe it needs to be solved with runtime checks. The specifics of which I'm still exploring but its worth mentioning these would only be necessary to tighten existing lifetimes so one can envision annotations or compiler options to elide these if desired.
Lifetime inference in MLKit (and I believe ante as well) tends to speed things up by turning more dynamic allocations into stack allocations, so there is some room there for runtime checks without making the result more expensive than the version with dynamic allocation I believe.
Ack, my apologies, I didn't intend to be so inflammatory! If memory serves AFL was one of the first schemes (or perhaps the first?) to abandon the stack discipline to provide better inference in quite a few cases compared to TT. I remember the graphs in that paper giving me more hope for region inference to be a practical memory management scheme. Later, I believe the imperative regions paper improved on the AFL scheme a bit at least in their single 'life' example, but without more test cases or graphs it is more difficult in general to assess that paper or how common this case matters in practice.
I'm curious what you believe the future of research for region inference to be considering most of the papers written after TT's retrospective paper seem to have moved in the direction of explicit regions rather than inferred ones.
Entirely joking about being offended, that work was a long time ago. I think it was an interesting exploration but we were not able to get compelling results, I think mostly because we did not at that time have affine types (move semantics). Thus if you put something into a container in one place and took it out in another, it would have to infer the region that spans both, which might as well be the whole program in most cases.
These days I program in Rust and find Rust's approach to explicit regions to be a workable compromise, though reference-heavy types can get pretty ugly and hard to work with (and I'm pretty sure that variance of lifetimes is confusing to everybody who isn't a PLT theorist and some who are).
The approach I personally find most interesting is the Lobster language. There (and I'm probably oversimplifying) the semantics are reference counting, but you so analysis to remove a huge fraction of RC operations. I believe the Perceus work is similar.
I'm happy to chat anytime. Recent work has been using somewhat exotic types provided by Rust (associated types, existentials, lots of inference through product types) to represent UI. So far I've basically been using what Rust gives me, but it's interesting to imagine what changes to the language/type system might buy you. For example, there are a few places in the code where there are downcasts, but I suspect that with a sufficiently strong type system you could prove those downcasts are infallible.
I’m curious what the rationale is for not making regions explicit in the source code. It seems like a downside of region inference for a systems language is the unpredictability of the inferred regions.
I maintain a JIT compiler for a very high performance Haskell like functional programming language. The compiler automatically generates the minimum malloc/free calls, mirroring the hand written code of an experienced C programmer. It works really well and the generated machine code was shown to be faster than hand-written optimised C++ code that people had been maintaining for years. The compiler code is unfortunately closed source and I have zero interest in writing academic papers so I wont elaborate further. Just telling you to hint hint perhaps try something like that :) The execution flow analyser was a b** to get right but worth it. I also recommend checking out some of the recent LEAN 4 papers. Some of those papers are moving in the right direction.
>However, without a license, the default copyright laws apply, meaning that you retain all rights to your source code and no one may reproduce, distribute, or create derivative works from your work.
What do you think is more likely, that the author forgot to add a LICENSE file or that he actually doesn't intend for ANYONE to use the language he created? Give me a break
The original comment was asking if the current legal status is that nobody is allowed to use ante without acquiring a licence separately (which is true) not whether the author's intention is that nobody use ante (which we don't know, but it seems unlikely.)
I thought the original comment was simply a big report: missing license file. With a snarky comment tagged on. I thought everyone assumed that, being shown by the author here, it was the latter.
(1) Zero-cost Effect Handlers by Staging: http://ps.informatik.uni-tuebingen.de/publications/schuster1...