
Algebraic Shape Composition in a tiny functional language
Last week i built a little side-project, Clape (https://github.com/zweiler1/clape), a very minimal funcrional programming language built around composable shapes instead of nominal types.
The core idea is that you don't define types but rather describe shapes and compose them using & for products and | for sums. Here are two examples of the language for a quick glimpse at it:
use Print
let Option<T> = Some(T) | None
let get_first<T> = (list: [T]) -> Option<T> {
match list {
[] => .None;
head :: tail => .Some(head)
}
}
let _ = print {get_first []}
let _ = print {get_first [1, 2]}
let _ = print {get_first ["hi", "there"]}
Output:
.None
.Some(1)
.Some("hi")
and
use Print
let Point2D = x(Float) & y(Float)
let Point3D = Point2D & z(Float)
let add = (p1: Point2D, p2: Point2D) -> Point2D {
.x(p1.x + p2.x) & .y(p1.y + p2.y)
}
let get_x = (p: x(Float)) -> Float {
p.x
}
let p1 = .x(2.3) & .y(3.4)
let p2 = p1 & .z(4.4)
let p3 = p2 & {add p1 p2}
let _ = print p3
let _ = print {get_x p1}
let _ = print {get_x p2}
let _ = print {get_x p3}
Output:
.x(4.6) & .y(6.8) & .z(4.4)
2.3
2.3
4.6
I kept the languages scope as minimal and focused as possible, so i think it's learnable in under an hour, or even less if you are familiar with functional languages. So, if you want to read more about it, the entire language documentation is in the repos readme, as it's really not that much.
I’m very new to functional languages in general (i mainly use C++, C and Zig nowadays), so this was mostly a small exploration project. I wanted to experiment with interpreters before adding compile-time execution to my main language (Flint). The experience has been surprisingly fun, as the language scope was so narrow too.
I’m posting here because I’d love feedback from people more experienced in FP:
- Is this kind of structural shape composition similar to anything that already exists in other languages? (It seems to me like Row Polymorphism could be similar to this system)
- Does the core idea feel useful to you or is the language basically just a copy of language X? I only have experience in imperative languages and took some inspiration from Ocaml syntax regarding Lists (cons operator) for Clape.
Disclaimer: I used an LLM in the early commits to get the interpreter and parser up and running quickly. It suprised me with a pratt parser (i never wrote one myself before). Nothing anyLLM did was just blindly accepted, I carefully reviewed and rewrote it all. But i still used them as this project was meant as a fun exploration project. I hope that's understandable for you all.
Edit: Formatting of code blocks and output, it somehow escaped a lot of stuff with \...
Edit2: Changed product type example to better showcase what I mean with shapes
Edit3: I now understand that the entire language is essnetially just purely strucutal typing of structural sums (exact same as TypeScripts union types or OCamls polymorphic variants) and structural products (which is just row polymorphism). So, there is nothing new or novel about it, only the syntax and coherence of it, but other than that it's just a rehashing of already known concepts. Thanks to everyone who answered :)