How expressive is fuse? How long are equivalent programs written in fuse/rust/scala/haskell?
Can you show me a bug that the fuse compiler catches but some or all of the competition doesn't?
It looks like a tidy little functional language - a small, easily grasped syntax surface and generally clear semantics. That you've got it to the point that it can compile and run proper programs is a great achievement for a solo dev project!
The string type in the standard library isn't Unicode-aware, might be worth just noting that. Unicode support can be a big undertaking, but considering whether you'll add it later or not might affect your library design now.
I don't really understand why you have an IO monad. The language isn't pure - `.exec()` means any function can perform IO actions no matter its type signature - so what's IO really for?
Do `impl` additions export? What happens when two libraries add the same function name with different signatures (or just bodies!) to a type's `impl` ?
Is currying automatic? It doesn't seem to be, but, eg, the `sum(x: i32, y: i32)` function theoretically could be called as `sum(5)` to create a closure, but this isn't a documented feature if so.
The website's font is using ligatures, not unicode operator symbols - I'd personally find it much clearer to use a non-ligature font to show what's really there, but that's immaterial to the language.
Yeah GRIN is a great project, it took a lot of debugging and analysis to make it compile 100% especially with monomorphization involved.
I'll look into Unicode support, makes total sense. Didn't scope it in initially. I can fix the site ligatures too, that's a fair remark.
> I don't really understand why you have an IO monad. The language isn't pure - `.exec()` means any function can perform IO actions no matter its type signature - so what's IO really for?
That's a fair point, I still left a place for `.exec()` to happen as un-handled side-effect. But the preference is with using the IO monad as the stdlib is built around it, with `main() -> IO[i32]` as a type signature. As languages evolves I'm planning to build a runtime around IO execution, and build more constraints for handling strict side-effects. However for this initial stage of the language, I left it as a really simple solution.
> Do `impl` additions export? What happens when two libraries add the same function name with different signatures (or just bodies!) to a type's `impl` ?
For now the language doesn't support modules (libraries), I'm planning on adding it. At the moment it's a bit of undefined behavior, as overloading would occur with latest `impl` definition.
> Is currying automatic? It doesn't seem to be, but, eg, the `sum(x: i32, y: i32)` function theoretically could be called as `sum(5)` to create a closure, but this isn't a documented feature if so.
In the type-system it is automatic, and it successfully passes type checker as it's entirely built on top of lambda calculus. But there's an issue with codegen right now. I can def look into it and document it.
I know jShell has been here like 10 years, but I'm not sure it's convenient to quickly write to a file, query a url, etc.
.ksh for Kotlin? Typescript (through Deno)? Lua?
trait Functor[A]:
fun map[B](self, f: A -> B) -> Self[B];
This looks a little wacky to me. I see that you can write HKTs in their η-long form and refer to them unapplied (`Functor`). But I don't understand how I would use this syntax to attach something to the trait that _doesn't_ depend on `A`. For (a silly) example, trait SizedFunctor[A]: Functor[A]:
type Size;
fun size(self) -> Size;
How do I know that `List[A]::Size` is the same type as `List[B]::Size`?Relatedly, I want to read `Self` in there as ‘the thing that implements `Functor[A]`’ (e.g. List[A]`), but that makes `Self[B]`, instantiated, mean `List[A][B]`, which I think should be a kind error.
fun map[Self: Functor, A, B](self: Self[A], f: A -> B) -> Self[B];
Since `Self` is the unapplied constructor, `Self[B]` just means `Functor[B]` e.g. `List[B]` not `List[A][B]`.The example you've shown with `SizedFunctor` is not currently supported, as support for associated types is not yet implemented. I got it on the roadmap tho!
trait ConvertTo[T]:
fun convert(self) -> T;
Seems to create a single trait ConvertTo, for a generic type with a [T] argument, rather than allowing one to define separate implementations for ConvertTo[i32], ConvertTo[String], etc.They can't even represent Fuse's Functor example, i.e.
f: A -> B, x: F[A]
so maybe they don't get any points for syntax.For example I’ve this config in helix:
[[language]]
name = "fuse"
scope = "source.fuse"
file-types = ["fuse"]
injection-regex = "fuse"
comment-token = "#"
indent = { tab-width = 2, unit = " " }
auto-format = true
formatter = { command = "fusefmt" }
[[grammar]]
name = "fuse"
source = { git = "https://github.com/stevanmilic/tree-sitter-fuse", rev = "eb5698f4867a4192064e54a92be280f4d2130e03" }