Soft question: functional programming in rust feels 'clunky'

The Monad abstraction doesn't "just work" for Rust. (@withoutboats on Twitter.)

The biggest problem is borrowing across ">>=", which is why async/await exist with the underlying immobile generator work: to allow for writing normal borrowing Rust code in an async context.

Second: how do you interpret return, break, ?, and other imperitive control operators inside a Monoid context? Third: higher kinded polymorphism doesn't work cleanly in the existing Rust type system, and the fact that Fn/Once/Mut exist splits everything even more.

Monads are powerful and work great to solve a problem in the lazy thunk boxed world of FP. In the imperative, (implicit-) allocation-averse, eager world of Rust, there are a lot of problems introduced that make the problem a lot more complicated than "just use Monads".

If you can solve all the problems in the linked twitter thread, I'm sure the community would love to hear it (and honestly, you might be able to convince someone to publish it). Until the day these problems are solved, though, "use Monads" is far from a constructive position to hold until you put a lot of qualifiers on it.

Instead of borrowing, I use Rc and the cloning when possible. This is not a perfect solution, but it works.

I don’t use the return and break as they are not «functional» enough. In case of syntax sugar Rust might just interrupt the compilation with error. I don’t see nothing bad here. Regarding ?, I encode it manually within my computations if required, but my computations are more numeric than IO-bound ones (discrete event simulation). Probably, the error handling can be added with help of combinators.

Moreover, the approach applied in the F# computation expressions doesn’t require a higher kinded polymorphism, as far as I understand. It is sufficient to define so called the «computation builder» for each computation type. This is not so general approach which is applied in Haskell, but it works.

I did not decide what to do with my code. This is a port of the most part of my Aivika simulation library that I wrote in Haskell before.

1 Like

The quoted format is how the rustfmt would print it, though, isn't it?

I definitely had a lot of that same pain. As I've come to understand rust better, it's receded and I've come to think that the deeper understanding is well worth it. The balance the language strikes with deref coercion eliminating lots of unnecessary *s and &s, but still requiring them where there's ambiguity about the programmer's intent is just about right for the seasoned programmer, but it can certainly make it a bit harder to get going initially. I also have benefited greatly from the excellent compiler suggestions.

1 Like

What is a good in depth resource on deref coercion? This is something that I am definitely struggling with, but did not realize it until now.

1 Like

Probably Treating Smart Pointers Like Regular References with the Deref Trait - The Rust Programming Language is the best place to start, but reference - What are Rust's exact auto-dereferencing rules? - Stack Overflow also looks useful.

1 Like

I think you should undestand that the conception of the functional style programming is high level itself. It shines with high level languages like Lisp but Rust is not of them. It just has some of the high level functional style facilities (among the others). Perhaps you just should not to use them when they do not look properly or well-reasoned. I, personally, see no cryme in it. Anyway using "Lambda just for Lambd" looks a bit childish to me.

1 Like