Bouncing between rust / haskell.. could rust elide types in trait impls?


#1

EDIT - see RFC https://github.com/rust-lang/rfcs/pull/2063

Context: my background is C++, and I’m experimenting with rust & haskell a little. (Haskell makes so much more sense after using Rust traits, originally it bewildered me…)

One complaint I had was ‘the need for single-function traits’ for overloading, which gets very verbose… especially as I like to break functions up as much as possible to exploit repetition in their guts. For example, a generic ‘Lerp’ (a+(b-a)f’ can be built on a generic ‘MulAdd’ (a+bf). And so on. They’re both one line functions. MulAdd appears again in extrapolation, etc etc.

Over in Haskell, it feels a bit less oppressive because you can write the type declarations in the ‘type class’, then just the function bodies (minus types) in the ‘instances’ - so we still have to declare bounds, but it doesn’t involve as much repetition as in Rust.

Would it theoretically be possible to mimic this behaviour in Rust aswell?

trait AddScaled<A,S>
{
   fn add_scaled(&self,a:&A: s:S)->Self;
}

// e.g: Point+Vector*Scalar-> Point
impl<S> AddScaled<Vector,S> for Point where ..
{
   fn add_scaled(self, a,f) { self+a * f} 
  // ^^ types are computed from the 'impl' params and 'trait' def
}

this might not sound like much, but the experience was "very easy to do in C++ -> hugely verbose in Rust -> OK in haskell (after learning the idea of type classes from rust, and finally persuading my brain to read space seperated function parameters…)

the other thing that is a bit messy is the mental flipping of the parameter order; again, doesn’t look like much , but with lots of single function traits it gets hard both to read and write inside the mess of angle-brackets going on… (I guess haskell is benefitting there from not having a special ‘self’, although that does allow some avoidance of repetition; the issue is that the self-parameter is ordered differently, whereas in haskell you can order all the parameters as they appear in the function itself…)

for this my request would be to allow an alternate ‘impl’ syntax similar to how it used to be, e.g. ‘impl Type : Trait’ or ‘impl Type as Trait’ … then the 'Self … ’ mimic what you read in function signatures ; it would also mimic what you see in casts ( the <Type as Trait>:: syntax… )

//        much easier to read/write, 
//         because of symmetry between
//         the trait and the function
//
//  "I want to implement this function call ..."
//     point .add_scaled(vector , scalar) //-> Point 
//                                 "...so what do I write?" 
//         /         |      |    /
impl Point as AddScaled<Vector,S> where S:.. Point:  Vector:...
{//   /       /            |   |                  //no swapping back and forth as you read/write
   fn     add_scaled(self, a,  f ) { self+a * f}  // to the trait & impl are more coherent
}                                                 // with what you think, read , and write
// |
//denoise the impl by allowing 'where' to define the type-params..  
// no need to write them *3 times*.. just once in the trait, and once in the where
// or once in the impl and once in the trait

#2

I’ve wanted something like this for a long time.

I would go even further and allow something like closure syntax when impl-into the trait functions, for maximum brevity.

I understand the reason why rust forces function signatures but this rationale breaks down imho for traits since the trait already provides a signature and hence self documents.

Consequently it causes an implentor overhead that doesn’t really buy anything imho, just adds syntactic noise to the source file, and also makes me less likely to impl a bunch of trait functions right away because I have to type a bunch of stuff.


#3

https://github.com/rust-lang/rfcs/pull/2063

i’ve made an RFC for this , if anyone wants to help get behind the idea