3
lorentz
328d

Rust's Fn traits feel weird. The argument tuple is a generic parameter, but the return type is an associated type, even though Rust is supposed to use Hindley-Milner type inference, so inferring through return type should always fail if this were a regular trait.

Then, this would mean that blanket implementations for Fn(T) and Fn(T, U) should conflict because AnyTrait<(T)> and AnyTrait<(T, U)> aren't mutually exclusive. I tried, they work just fine.

There's some weird and I suspect unnecessary special case magic here, and I'd like to uncover it.

Comments
  • 0
    @jestdotty what's your opinion about this?
  • 2
    @retoor fn traits are cool when i've used them

    In js I wrote a music library and I wanted to rewrite the same library and make it in rust (the js one lagged a bit and I was using that library for games and I wanted to use something similar with bevy)

    But the lower level lib I chose had a bunch of fn traits and that was before I could reason about them (https://crates.io/crates/fundsp)

    Chances are even now I still won't know how to use the library though
    Their examples were not exactly what I was looking for

    Whether fn returns should be as they are theoretically or not I don't know
    And for some reason I can't comprehend math notation as a human being
  • 3
    @jestdotty I get that, type theory is the very edge of my mental capacity. I need to sit a while in quiet and darkness and envision the patterns in my head in order to make progress, and I only ever write it down to explain to someone else.

    It doesn't help that Rust doesn't use established jargon and since I mostly write Rust I end up adopting their names.
  • 2
    Thanks for FunDSP, making computers make pretty noise is a longtime project of mine.
  • 2
    I don’t understand it but it turns me on 😏
  • 1
    Haskell has it, almost no explicit types, same for ocaml... Yet Rust... Does it really have a real one? Hmmmmm... I mean, it can't infer shit by itself
  • 1
    @kobenz if you mean type inference, Rust has a lot of it, but clearly not as much as Haskell. I like this actually, one of the things that bug me about Haskell code is that deducing the type of a binding isn't a trivial task.
  • 2
    There's a plugin that tells ya what the inferred types rust is seeing are (which incidentally can infer more than rust actually can in some occasions...)

    It is weird to have to "start with the end"

    Such wisdomz
  • 2
    Turns out that fundsp library has went from 0.9.0 to 0.16.0

    It was the first thing I tried to do in rust and I hadn't gone back to it since

    Doesn't help I'm not an audio engineer, ahhh

    Also turns out I was just confused about one anonymous function 🤣, so it's not even really that function heavy...

    Your first exposure to rust being so generic heavy though is something. Perhaps I like masochism
  • 0
    @lorentz, you're trippin balls, man. write some ocaml or haskell and check out how much actual typing you need with a real Hindley–Milner system.

    Rust's degenerated into wtv it is nowadays. It's like some bored programmers wanted a virtually bloated language without actually bloating anything and now not even Hindley–Milner can save it.
  • 0
    @kobenz Haskell doesn't need annotations because
    - typeclasses are more expressive than rust traits
    - values can be generic, in rust generics have to be fully monomorphizable

    This means that aggregator types which only represent what you can do with a value are much rarer.

    And as I mentioned, the fact that type annotations are more common in Rust is a good thing in my opinion. If the language has to work hard to deduce the types, the reader would probably have to work hard too, and that is wasted effort.
  • 0
    @lorentz untrue, neither GHC nor ocamlc do any heavy lifting, just bench them against rustc. rustc is always the slowest with bigger binaries

    All three are type correctness bloodhounds.

    I mean, have you read some of rustc's assembly? Fucking thing is unreasonable o.O
  • 0
    @kobenz The slowest part of rustc is by far the borrow checker, which infers a lot more than the type checker, but that's because lifetimes never influence behaviour, so the developer doesn't necessarily have to be aware of the inferred values as long as they're valid. Types contextualize all behaviour so it's critical that the developer understands all of them, and frequent annotations help with that.
  • 2
    @lorentz

    if you write a HOF that folds it's arguments into a single one, rust throws a tantrum and will fail to infer such HOFs signature

    Neither ocaml nor haskell will complain, in fact, besides inferring such HOFs type, both will succeed in type checking any usages of that HOF.
  • 0
    @lorentz rust's type inference, currently, has a mild case of typescript mediocrity
  • 0
    @kobenz That's exactly the type of thing I'm talking about. The signature of a function should only ever be inferred from its usage never from the body, and only if there's a single point of use which provides all the necessary information. If the compiler needs to take several unification steps, it should be spelled out for the human reader anyway.
  • 0
    @lorentz therefore Rust doesn't have a Hindley–Milner type system because it can't infer the most basic HOF
Add Comment