Live data from Hacker News

Show HN: Fuse – statically typed functional programming language

fuselang.org

41–49 of 49 posts

Re: Show HN: Fuse – statically typed functional programming language

#41

Earlier quoted context omitted.

Haskell is a great language with a really advanced type-system, although I found its syntax hard to read at times especially as I was exploring the language at first. On the other hand I really liked how Rust syntax was defined in terms of ADTs, Traits & Methods Impls, with type signatures required for functions. Hence I wished for a similar functional language that has such write-style and type concepts, but strippi…

Just as general feedback, I think your experience matches up with more software developers than the GP. Haskell is really obtuse and unreadable for those who are not accustomed to it.

ELM being a lot more popular than Haskell with mostly the same syntax would indicate that it is not the syntax, that people find hard with Haskell.

Re: Show HN: Fuse – statically typed functional programming language

#42

Just curious, what made you choose GRIN? I haven't heard of it but it looks neat!

As I was deciding on the compiler backend, I stumbled upon on it in r/ProgrammingLanguages on reddit. I liked the syntax itself and the fact I can compile the language in the IR of a mini functional language; with a lot of benefits in terms of optimizations. Especially as (strict) pure functional language are notoriously slower than imperative language because of lack of mutations. Allowing me to have a higher-order functional language that has zero cost abstractions.

Re: Show HN: Fuse – statically typed functional programming language

#43

Can I write a game using OpenGL in this language? Does its functional purity allow this?

Technically yes, although there's no support for FFI yet. Purity would allow it as long as side-effects are wrapped into IO type.

Re: Show HN: Fuse – statically typed functional programming language

#44
post #36

Earlier quoted context omitted.

`Self` isn't the applied type (`List[A]`), rather it's the type constructor of kind `* -> *` constrained by `Functor`. In the map example it gets desugared into: 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 suppo…

Right, I got the notion — but syntactically I expect `Self` to refer to the thing named at the top of the block, which is a `Functor[A]`. I think what both I and the sibling comment are getting at is that there is a difference between `Functor : (Self : * → *) → Class` and `Functor : (Self : * → *) → (A : *) → Class`/preapplied `Functor : (Self : *) → Class` and the syntax seems to merge the two (using syntax for the…

Fair point, I don't disagree with the statement that `Self` can be limiting as the trait is defined for `Functor[A]`. Thus imposing limitations on type system.

You would want for type variable to not be attached directly to a type class on its definition? But still treated as a container type. Something like:

    trait Functor:
        fun fmap[A, B](f: A -> B, c: Self[A]) -> Self[B];

     ...

    impl Functor for List[A]:
        fun fmap[A, B](f: A -> B, l: List[A]) -> List[B]
            List::fold(l, Nil[B], (t, h) => Cons(f(h), t))

    ...
The above would compile, but the Functor wouldn't be treated of a higher kind in the type-system. I'll try to work a flexible solution, thanks for the great callout!

Re: Show HN: Fuse – statically typed functional programming language

#45
post #39
post #32

Earlier quoted context omitted.

Luau is statically typed and interpreted/JIT'd: https://luau.org/

Oh, nice, I didn't know - I always thought that Luau has only type annotations and is not statically typed per se. But yeah, looked into the documentation and you can set !strict mode per script, which will cause interpreter to assert the types. Looks promising. Can you tell me how well it works in practice?

I've only used it for small scripts and can't say how well the type system actually functions/how it scales, but what I've seen so far has pleased me. (They have a _comptime_-equivalent! https://luau.org/types/type-functions/)

You may be interested in https://lute.luau.org/, which is a node.js-style runtime for the language.

Re: Show HN: Fuse – statically typed functional programming language

#46
post #25

Nice to see a pretty advanced language at frontpage of HN! From what I understand, GRIN does some parts of supercompilation [1] during optimization process. Supercompilation can prove equivalence of functional programs [2] modulo termination. So you can have something interesting and useful in almost no time. ;) [1] https://themonadreader.wordpress.com/wp-content/uploads/2014/04/super-final.pdf [2] https://www.resear…

This is great, I haven't been introduced in the notion of supercompiliation. Reading the papers you've listed and going through GRIN's paper [1] it ticks the boxes in terms of laziness and graph reduction. To keep the implementation of Fuse simple I've decided on using strict evaluation of GRIN programs instead of laziness, with my assumption that it would harder to debug/reason on the program. However, this was one of my next improvements: switching to a lazy evaluation with similar semantics to Haskell programs.

> It appears that Fuse does not have user-defined operators. Am I right?

Not yet, but I left this mechanism completely open. As operators are defined as type classes with their signs as method definitions.

  [1] http://nbviewer.jupyter.org/github/grin-compiler/grin/blob/master/papers/The%20GRIN%20Project.pdf

Re: Show HN: Fuse – statically typed functional programming language

#47
post #20

Off topic: what is the most convenient statically typed language that don't require compilation/transpilation? To run instead of bash or Python, but types are mandatory (not just hints like python). 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?

One more, in Dart:

https://lazebny.io/i-stopped-writing-bash-scripts/

Re: Show HN: Fuse – statically typed functional programming language

#48
post #36

Earlier quoted context omitted.

Right, I got the notion — but syntactically I expect `Self` to refer to the thing named at the top of the block, which is a `Functor[A]`. I think what both I and the sibling comment are getting at is that there is a difference between `Functor : (Self : * → *) → Class` and `Functor : (Self : * → *) → (A : *) → Class`/preapplied `Functor : (Self : *) → Class` and the syntax seems to merge the two (using syntax for the…

Fair point, I don't disagree with the statement that `Self` can be limiting as the trait is defined for `Functor[A]`. Thus imposing limitations on type system. You would want for type variable to not be attached directly to a type class on its definition? But still treated as a container type. Something like: trait Functor: fun fmap[A, B](f: A -> B, c: Self[A]) -> Self[B]; ... impl Functor for List[A]: fun fmap[A, B]…

Right, so the definition of higher-kinded types is that the _parameter_ to the trait (here, `Self`) is higher-kinded (here, `* → *`) not that the trait is parameterized. So `impl Functor for List[A]` is not (semantically) correct: it's not `List[A]` that implements `Functor` but `List` itself.†‡ The important thing you get out of that is precisely the ability to talk about these kinds of universals: you can associate items to the type constructor itself before its eventual parameter is even in scope, and so the value of all such things must be the same independent of the parameter ‘for free’. As soon as you introduce the type parameter you incur a proof burden if you want to claim that the associated item is the same regardless of the value of the parameter, because you have introduced the syntactic possibility that they could vary.

† There's an encoding of higher-kinded types in some languages that don't really have them as first-class citizens (e.g. Rust with associated type constructors) that does this by adding a ‘rewrap’ item to the trait: you implement `Functor` for `List`, but also (as part of the trait) includes a type constructor `Rewrap = List`. This lets you encode the fact that the `Functor` instance is defined for `List` for all values of `A`, but you still struggle to prove that some of their items are independent of the choice of `A`.

‡ To see both of these side-by-side, consider the instance for pairs, which are functorial in their right parameter (as well as the left parameter: they are bifunctorial, but that's not relevant here). So if you have a curried pair type constructor `Pair : * → * → *` it really is true that `Pair[A]`, not `Pair`, is a `Functor`:

    impl Functor for Pair[A]:
        fun fmap[B, C](f: B -> C, self: Pair[A][B]) -> Pair[B][C]):
            Pair(self.0, f(self.1))
Post reply on HN