Hacker News new | ask | show | jobs
by chridou 2023 days ago
Even though I see that these language capabilities remove restrictions I hope that HKTs and with them Functors, Monads, etc. will never make it into Rust.

The thing I like most about Rust is that it is still a practical language where I can still solve my problems in different ways and always know what will happen. I also care about the "how" and not only about the "what".

Everything being F[_]ed is what I do not need anymore.

3 comments

Functors and Monads already exist in Rust, you just can't talk about them in the trait system. Option, Result, and Future are all both Functors (map) and Monads (and_then). You've probably used them without even knowing, because we didn't give it some weird, unlearnable category theory name.

If someone were to create an explicit trait for them and RFC it, they'd probably name it something like Map and Then rather than Functor and Monad.

If someone asked me if I've ever used functors or monads in Rust, I would unequivocally say "no, I haven't." And I would say that because I've never written code that's generic over functors or monads.

I think this kind of "you've already used functors or monads, they are just scary names" retort is really missing the point of what folks are complaining about.

Right, but I can think of a few cases where one might want to be generic over effect systems; especially in library code. For example, you could have a parsing library that accepts both blocking and non-blocking I/O streams. You need a Map/Then trait in order to express that generically.
I didn't say there weren't any use cases. Of course there are use cases.

I'm not even taking a side here in this thread (although I have advocated against functors/monads in the past). I'm saying that your comment is missing the point of folks who are skeptical of things like functors and monads.

> Option, Result, and Future are all both Functors (map) and Monads (and_then).

No. They are Option and Result and Future.

> You've probably used them without even knowing, because we didn't give it some weird, unlearnable category theory name.

No. I have not used them without even knowing. I have used Option, Result and Future. I do not need some meta-universe which just makes easy things more complicated by stating some laws which types must hold just for the sake of discussing them and have the one ring to rule them all.

> and have the one ring to rule them all.

It's not a ring, it's a monoid; there's (in general) no negation.

It could be argued that understanding the commonality of certain aspects of Option, Result, and Future results in a simpler model rather than a more complicated one.

Don't you find it intriguing and interesting that these seemingly different types have these commonalities?

Well, you somehow got me. When I mentioned the "everything F[_]ed" in my top post I thought I'd made it clear that I knew the commonalities.

And I have to admit that I find these commonalities very fascinating. I can still remember how I enjoyed applicatives and the like when I started with scalaz back then. Whether the model becomes simpler? I do not really know. I just found out for myself that I do not need this knowledge at work and that it didn't really help me to solve my daily problems. This is actually what drove me to Rust which in my perception is a nice practical "in between" (I know it also is no silver bullet).

You will probably not see much Haskell style functional programming in Rust simply because there is no garbage collector in Rust, and Haskell depends on one very much.
It isn't immediately obvious that FP requires GC. Sure, the languages we have right now make use of GC, but it is far from certain that there is no way for a subset of FP features to exist in a language without GC.
The F in FP definitely hugely benefits from GC. Closures in Rust don't compare to Haskell.

Combine that with GHC's optimizer and it's no contest which language to choose if both ergonomics and performance of code written largely as lambdas is your priority.

With linear types you could get rid of the GC, probably.
The core issue here isn't exactly GC, though it is related. The issue is that abstraction is about hiding things, and Rust's type machinery is about exposing things. In Haskell, you have lambdas, and you have types of all of the same size data, because it's all on the heap. In Rust, each closure is a distinct type, plus the three different types of closures, plus types of different sizes...

It's not so much the GC, as it is "in a GC'd language, everything is on the heap and a lot of information (from Rust's perspective) is erased." You may be able to get rid of GC in some sense, but you'd end up with something halfway to Rust, not the whole way.

> Rust's type machinery is about exposing things

That makes sense, thanks for explaining that, I am used to Haskell but never used Rust.

Hm ATS is prior art re: linear types and closures. It's definitely not the same.

That said, -XLinearTypes in GHC 9.x will open up a world of memory management capabilities in library-space for Haskell. Very exciting stuff! If you push the heavy stuff off-heap, then the GC just becomes a slightly fancier arena allocator.

I'm very interested in that. I was using zig for a while, and I wish I could build my own (simple) memory allocators for certain things in Haskell like that. I have a project where I want to be able to directly control the memory layout of the data structures but since that's just a tiny part of the whole program I don't want to build the whole thing in zig or something like C, I prefer Haskell for this specific purpose (it's a stream processing application with a small [code-wise, the data set can be huge] in-memory tree database which I want to be able to do the memory object allocation for myself).
Another reason GC is nice: FP tends to rely on immutable linked data structures with pervasive sharing. That makes ownership complicated.
I'm working on fixing that ;)

Unfortunately we don't yet have covariant associated types, so my GC is a pain to use.

In all seriousness, I'm not sure if Rust will ever be a great fit for abstract high level programing. The syntax is just too verbose, and lifetimes are a leaky abstraction. It might make a good compiler target though. At the very least next generation FP needs to have a great Rust interop story.

The exact same argument exists for not hiding IntList and StringList behind fancy generics like List[I], which obscure the how.