3 ms·
> As a matter of fact such reflection is only needed because languages like Java or C# have very weak static type systems, compared with other languages in the
by louthy 8y ago
> As a matter of fact such reflection is only needed because languages like Java or C# have very weak static type systems, compared with other languages in the ML family. With an expressive type system, you never need reflection capabilities.
The implication here is that you never need runtime type checking, which clearly isn't the case in ML family languages. Sum types for example have an abstract representation that must be resolved at runtime (for pattern matching).
C# also doesn't need reflection to resolve types (other than through the virtual route - i.e. inherited method resolution), this is a core feature of the CLR though (via `callvirt` [1] if I remember right) and not a weakness of C#'s type-system. C# bakes the concrete generic types into the generated IL.
[1] https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.callvirt?view=netframework-4.7.2 https://docs.microsoft.com/en-us/dotnet/api/system.reflectio...
- bad_user 8y ago> Sum types for example have an abstract representation that must be resolved at runtime (for pattern matching). Indeed, but that's plain tagging, which is basically an int and not the same thing. "callvirt" is basically doing a virtual method lookup in a vtable. It's still at runtime, but we are talking about OOP polymorphism now and how late binding works. Languages with type classes don't need that either, but that's a separate discussion and note that I still like OOP. > C# also doesn't need reflection to resolve types No, the developers do, because the language is not expressive enough to express generic pieces of code without losing type info, so you need reflection for constraints (e.g. "new T" or "instanceOf" checks) and runtime guards for downcasting. Classic example: express a "sum" function that works on any Array<A>. And note that what F# is doing to solve this particular problem is a hack to workaround both the lack of higher kinded types and of type classes and that does not interoperate with C#, since it requires "inline functions" which are doing type erasure (and it's a big and ugly hack, speaking of ML, because inline functions are no longer values ;-)). > C# bakes the concrete generic types into the generated IL. Of course, but that too is part of the problem.
- louthy 8y ago> No, the developers do, because the language is not expressive enough to express generic pieces of code without losing type info, so you need reflection for constraints (e.g. "new T" or "instanceOf" checks) and runtime guards for downcasting. The type system is totally capable of it. The language doesn't make it easy, but the code below is essentially type-classes and class-instances if you squint. It's something the C# team are looking into now anyway, but the main point is the type system doesn't preclude it. public interface Newable<A> { T New(); } public struct NewableThing : Newable<Thing> { Thing New() => new Thing(); } public class Foo { public A Bar<NewableA, A>() where NewableA : struct, Newable<A> => default(NewableA).New(); } > Classic example: express a "sum" function that works on any Array<A>. public interface Num<A> { A Zero(); A Add(A x, A y); } public struct NumInt : Num<int> { int Zero() => 0; int Add(int x, int y) => x + y; } public struct NumFloat : Num<float> { float Zero() => 0; float Add(float x, float y) => x + y; } public static A Sum<NumA, A>(A[] xs) where NumA : struct, Num<A> => xs.Fold(default(NumA).Zero(), (s, x) => default(NumA).Add(s, x)); int sumInt = Sum<NumInt, int>(new [] {1,2,3,4}); int sumFlt = Sum<NumFloat, float>(new [] {1.0,2.0,3.0,4.0}); > Of course, but that too is part of the problem. That's a very hand wavey statement. It's the goal of all staticly typed compilers to resolve to concrete types at compile time. How is part of any problem? The CLR has the capability to generate new concrete types from generic types at runtime if required, but obviously tries to do as much of that work up front at compile time.