HKT is indeed on the long-term roadmap, but it remains to be seen whether a design can be devised that plays nicely with the fundamental features of Rust (note that the language reserves the unused `do` keyword for just this purpose). Doing this properly is very much research-project territory.
And unless I'm reading the RFC incorrectly, I think this is more principled than you're making it out to be. `FromError` is not magic or specially-handled by the compiler in any way, it's just a trait defined in the stdlib. The `try!` macro isn't calling any magic methods, it's just expanding to a pattern match that itself makes use of typeclasses. It's indeed true that this would only work with variants of the `Result` type, but I don't think that's especially heinous (users can easily supply their own specialized versions of this type, and almost always do). And if the `?` syntax is accepted, it will be able to be used with any type that implements the `Carrier` trait (which is sorta specially-treated by the compiler, though users can still override it via lang items), and would replace the `try! macro entirely. Nothing here is ad-hoc.
Finally, even if Rust had HKTs, I could be convinced that error handling in particular is important enough to require a dedicated syntax to set it apart.
`Carrier` is still pretty parochial; it has this normal/exception distinction hardwired into it, no? The RFC explicitly rules out using Vector with it, and it doesn't look possible to implement for async constructs, or STM transactions, or the like? I'd very much like to be wrong here.
FromError is not handled specially by the compiler, but it is handled specially by the try macro; does the signature of try make the relationship between the two more obvious? I haven't been following the state of Rust IDEs, but I'd hope that they can make it more obvious which typeclasses are involved than is clear from the text of the code (apologies for this awful sentence).
FWIW doing things this way doesn't rule out a dedicated syntax on top of it - see the recent SIP for async/await in scala.
> `Carrier` is still pretty parochial; it has this
> normal/exception distinction hardwired into it, no?
To reiterate my earlier point, I'm personally fine with the existence of an entirely separate mechanism for error handling. Mind you, not that this invalidates your desire for a more general mechanism for async et al. Until/if we get HKTs, we'll probably continue to achieve this with bespoke macros as per today's `try!`.
> FromError is not handled specially by the compiler, but it is handled specially by
> the try macro
The `try!` macro is just as non-special as `FromError` (and `Result` and `Option`). You're free to recreate the whole ecosystem in your own libs if you'd like (ignoring the `Carrier` proposal for the moment and its associated syntax).
> The `try!` macro is just as non-special as `FromError` (and `Result` and `Option`). You're free to recreate the whole ecosystem in your own libs if you'd like (ignoring the `Carrier` proposal for the moment and its associated syntax).
Sure. I'm coming at this from a viewpoint of a) syntax is very important b) user-defined macros are generally undesirable
> (note that the language reserves the unused `do` keyword for just this purpose).
I'm not entirely sure it's just for this purpose. `do` used to mean something in Rust, but when that syntax was removed, the keyword just wasn't freed up. Of course, if we do gain HKT, it will be nice to have it, but I'm not sure that was the justification at the time.
Removing the old notation was certainly not solely motivated by wanting to free up the keyword, but the reason that it remains reserved is in anticipation of future use, rather than simple negligence (though of course this decision could be reversed before 1.0).
F# doesn't have HKT, but still has a variant of do syntax via "computation expressions" http://msdn.microsoft.com/en-us/library/dd233182.aspx. It's less elegant than HKT because you have to name the monad used for the expression i.e. io { exprs }, and also involves additional boilerplate code to define them - but accomplishes many of the same objectives.
The problem is that without HKT you can't abstract over these things; you can't write useful functions like "sequence", and so code that uses these expressions becomes a kind of second-class citizen that can't be refactored the way you'd do with normal code.
Of course, HKT is preferable, just in the error reporting context (i.e. this particular example) I'm not sure much the addt'l abstraction (functions like sequence) further solves the problem, seems like the expressions described may be sufficient.
But I agree, in general, you absolutely want HKT for the reasons you mentioned.
Said another way, if HKT in rust is doable, let's do that - but if that turns out not to be the case, there are some nice conpromises such as this example, which I think, at least, is better than the proposed ? Operator, because it is a bit more general/versatile.
And unless I'm reading the RFC incorrectly, I think this is more principled than you're making it out to be. `FromError` is not magic or specially-handled by the compiler in any way, it's just a trait defined in the stdlib. The `try!` macro isn't calling any magic methods, it's just expanding to a pattern match that itself makes use of typeclasses. It's indeed true that this would only work with variants of the `Result` type, but I don't think that's especially heinous (users can easily supply their own specialized versions of this type, and almost always do). And if the `?` syntax is accepted, it will be able to be used with any type that implements the `Carrier` trait (which is sorta specially-treated by the compiler, though users can still override it via lang items), and would replace the `try! macro entirely. Nothing here is ad-hoc.
Finally, even if Rust had HKTs, I could be convinced that error handling in particular is important enough to require a dedicated syntax to set it apart.