(1) Zero-cost Effect Handlers by Staging: http://ps.informatik.uni-tuebingen.de/publications/schuster1...
(1) Zero-cost Effect Handlers by Staging: http://ps.informatik.uni-tuebingen.de/publications/schuster1...
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.
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!
C is great, and it would be cool to see something that is similarly close to the instruction set but has functions as values
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.
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.
[0] https://www.semanticscholar.org/paper/Functional-C-Hartel-Mu...
[1] https://ris.utwente.nl/ws/portalfiles/portal/5128727/book.pd...
(edit) add download link and background.
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.
OK, but vectorisation is exposed by the instruction set, as instructions[1]
> speculative execution, branch prediction, ... caches, MMUs
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?
But they are thoroughly ingrained into the technology, and will not easily be rooted out.
The more expressive your language is, the less the runtime and hardware needs to guess about.
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.
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.
Really, perhaps your language is The Next One.
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.
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.
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.
You will only know if you try. Things that are worth it take courage me thinks.
> 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.
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).
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.
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?
And yes, the dot product should be 32, thank you :)
As you have the normal map function for Functors (using Haskell):
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
you can have bimap for Bifunctors: > :t bimap
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
which specialised to pairs is: > :t bimap @(,)
bimap @(,) :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)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.
Seriously, this looks promising and I'm very interested to see where it goes.
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.
Joking aside, looks cool, good luck with the project!
:eyeroll:
>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.
Joking aside, looks cool, good luck with the project!