Remix.run Logo
simonask 10 hours ago

Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature?

AFAIK, it’s not really very common to be able to extend foreign types with new interfaces, especially not if you own neither.

C++ can technically do it using partial specialization, but it’s not exactly nice, and results in UB via ODR violation when it goes wrong (say you have two implementations of a `std::hash` specialization, etc.). And it only works for interfaces that are specifically designed to be specialized this way - not for vanilla dynamic dispatch, say.

lmm 5 hours ago | parent | next [-]

> Other than duck-typed languages (and I count Go as basically that), which languages actually provide this feature?

There are only like 3 significant languages with trait-based generics, and both the other ones have some way of providing orphan instances (Haskell by requiring a flag, Scala by not having a coherence requirement at all and relying on you getting it right, which turns out to work out pretty well in practice).

More generally it's an extremely common problem to have in a mature language; if you don't have a proper fix for it then you tend to end up with awful hacks instead. Consider e.g. https://www.joda.org/joda-time-hibernate/ and https://github.com/FasterXML/jackson-datatype-joda , and note how they have to be essentially first party modules, and they have to use reflection-based runtime registries with all the associated problems. And I think that these issues significantly increased the pressure to import joda-time into the JVM system library, which ultimately came with significant downsides and costs, and in a "systems" language that aims to have a lean runtime this would be even worse.

simonask an hour ago | parent [-]

Sure, the `chrono` library in Rust had essentially the same problem.

Scala is interesting. How do they resolve conflicts?

ThunderSizzle 9 hours ago | parent | prev [-]

C# isnt a duck type language (well, you can do that via dynamic keyword, but I don't know who would do that typically).

Most integration libraries in Nuget (aka c#'s cargo) are AB type libraries.

E.g. DI Container: Autofac Messaging Library: MediatR Integration: MediatR.Extensions.Autofac.DependencyInjection

There are many examples of popular libraries like this in that world.

simonask an hour ago | parent [-]

C# does not support adding interfaces to foreign types. It does support extension classes to add methods and properties to a type, but nothing that adds fields or changes the list of interfaces implemented by a type. Rust supports this as well, because you can use traits this way.

Dependency injection is a popular solution for this problem, and you can do that as well in Rust. It requires (again) that the API is designed for dependency injection, and instead of interfaces and is-a relationships, you now have "factories" producing the implementation.