News for hackers. Stuff that matters.
Re:Why is Idris 2 so much faster than Idris 1? by kibwen on Monday May 25, 2020 @04:52PM (#23304840)
> Rust promises full type erasure when you're not using "dyn"

I don't know if "type erasure" is the accurate term to use with the generic-specialization scheme that Rust uses; one can trivially write a generic Rust function that demonstrates that types, while inaccessible at runtime, still semantically affect the generated code:

    use std::mem::size_of;
    
    fn foo<T>(t: T) {
        dbg!(size_of::<T>());
    }
    
    fn main() {
        foo(1);  // prints 4
        foo("bar");  // prints 16
    }
Re:Why is Idris 2 so much faster than Idris 1? by TeMPOraL on Monday May 25, 2020 @05:19PM (#23305096)
Isn't this just compile-time dispatching? I think types 'inaccessible at runtime but still affecting generating code' are table stakes, and basically half of the point of doing these types of generics.

Equivalent C++ code (admittedly, C++ templates aren't really generics) would have enough information to shove literal 4 and 16 into the binary there.

Re:Why is Idris 2 so much faster than Idris 1? by kibwen on Monday May 25, 2020 @05:30PM (#23305186)
This is kind of my point, I've never heard the term "type erasure" used with static dispatch (and Rust code, for better or worse, overwhelmingly prefers static dispatch to dynamic dispatch).

Rust does guarantee type erasure on lifetimes, but lifetimes are only used for semantic analysis, and are completely separate from and unrelated to code generation/type layout.

Re:Why is Idris 2 so much faster than Idris 1? by Reelin on Monday May 25, 2020 @07:07PM (#23305825)
What do you mean by C++ templates not really being generics? Aren't Rust's generics also implemented as templates (as opposed to parametric polymorphism)?
Re:Why is Idris 2 so much faster than Idris 1? by neutronicus on Monday May 25, 2020 @10:38PM (#23306941)
Rust Generics are Parametric Polymorphism - you must pre-declare the allowed operations on the Type Parameters via Trait Bounds (essentially Haskell Typeclass constraints), and the Generic will fail to compile if you try to perform any other operations in the body (even if the Generic is never instantiated).

In C++ you can do any syntactically valid thing with the Type Parameter in a Template body, and it isn't type-checked until you attempt to instantiate it.

Re:Why is Idris 2 so much faster than Idris 1? by Reelin on Tuesday May 26, 2020 @01:23AM (#23307693)
Would it be correct to describe Rust's generics as parametrically polymorphic templates then? I'm still not seeing how C++ templates aren't proper generics though - parametric polymorphism isn't a requirement for that, is it?

I guess I had mistakenly thought that run time dispatch and a single binary implementation was somehow required for parametric polymorphism since it requires treating all types identically. Upon reflection I can see that it's not actually exclusive of compile time dispatch though.

From a pragmatic perspective it seems unfortunate that such generics can't be used in an API without corresponding access to the source code. I saw the ability to work with arbitrary future types at runtime as largely being the point of type erasure.

From a theoretical perspective I'm having some trouble accepting the idea that Rust generics are an example of true parametric polymorphism. In the earlier example a function could behave differently based on the size of the type. That's not uniformly dispatching to a behavior implemented by the type though, which seems like the core idea behind parametric polymorphism to me. (I suppose my concerns are purely academic though. AFAIK runtime reflection in Java allows utterly breaking type erasure but in practice Java generics still seem to be referred to as an example of parametric polymorphism.)

Re:Why is Idris 2 so much faster than Idris 1? by ncmncm on Monday May 25, 2020 @11:45PM (#23307216)
... which does also happen at compile time. Or before you instantiate it, if the template is declared using concepts, in C++20.

The effect without concepts is that you can (in principle) get things that "accidentally" match, like applying "+" to strings; and that the error messages when they don't match are unpleasant. Concepts resolve both.

Re:Why is Idris 2 so much faster than Idris 1? by ferzul on Monday May 25, 2020 @05:20PM (#23305115)
correct me if i'm wrong - i only spent a hours with rust: doesn't dbg! run at compile time? and therefore your example is still compatible with type erasure?
Re:Why is Idris 2 so much faster than Idris 1? by uryga on Monday May 25, 2020 @06:46PM (#23305705)
`dbg!(x)`, being a macro, expands to something at compile time; at runtime, that expanded code will do something like `write(x.fmt(), stderr)`. it's not relevant here, only `size_of` is.

what's happening here is that rust does "monomorphization" – it generates two versions of `foo`, one for ints and one for strings; then, in each specialized version, `size_of` is specialized to that particular type's implementation of `size_of` (compiler-generated), which returns 4 for i32 and 16 for <whatever that string type is>.

i'm sure it's actually more nuanced than that, but i think that's the general principle.

Re:Why is Idris 2 so much faster than Idris 1? by kibwen on Monday May 25, 2020 @05:39PM (#23305257)
I'm asking what we're referring to by "type erasure" here; one can use trait objects to erase a type in Rust, and size_of (which, yes, runs at compile-time (the debug macro is just for printing, not for const eval)) does indeed work on such type-erased objects, but it will always give you the size of the fat pointer to the trait object.