Remix.run Logo
deredede 4 days ago

I can think of plenty situations where you really want to use the dependency's types though. For instance the dependency provides some sort of data structure and you have one library that produces said data structure and a separate library that consumes it.

What you're describing with SML functors is essentially dependency injection I think; it's a good thing to have in the toolbox but not a universal solution either. (I do like functors for dependency injection, much more than the inscrutable goo it tends to be in OOP languages anyways)

shadowgovt 4 days ago | parent [-]

I can think of those situations too, and in practice this is done all the time (by everyone I know, including me).

In theory... None of us should be doing it. Emitting raw underlying structures from a dependency coupled with ranged versioning means part of your API is under-specified; "And this function returns an argument, the type of which is whatever this third-party that we don't directly communicate with says the type is." That's hard to code against in the general case (but it works out often enough in the specific case that I think it's safe to do 95-ish percent of the time).

int_19h 4 days ago | parent [-]

It works just fine in C land because modifying a struct in any way is an ABI breaking change, so in practice any struct type that is exported has to be automatically deemed frozen (except for major version upgrades where compat is explicitly not a goal).

Alternatively, it's a pointer to an opaque data structure. But then that fact (that it's a pointer) is frozen.

Either way, you can rely on dependencies not just pulling the rug from under you.

shadowgovt 4 days ago | parent [-]

I like this answer. "It works just fine in C land because this is a completely impossible story in C land."

(I remember, ages ago, trying to wrap my head around Component Object Model. It took me awhile to grasp it in the abstract because, I finally realized, it was trying to solve a problem I'd never needed to solve before: ABI compatibility across closed-source binaries with different compilation architectures).