crockeea
crockeea

Reputation: 21811

Getting safety and extensibility

I have a library that includes a type data Zq q = Zq Int representing the integers mod q. For safety, I'd like to expose some operations on this type ((+), (*), etc), but not export the constructor to avoid people circumventing the safety gotten by declaring such a type in the first place.

However, users of the library may reasonably need to declare instances for this type that I as the library author can't predict. To name just a few possible instances: DeepSeq, Storable, Unbox, ...

The only way I know of that allows third parties to make such instances is to export the constructor. (Alternatively, I could define and export a smart constructor and destructor, but this seems to be no better than just exporting the data constructor.)

Is there a way to ensure safety while also allowing third parties to extend the type?

Upvotes: 2

Views: 73

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

Most well-formed instances shouldn't require the unsafe raw constructors. Unbox etc. are a bit unusually low-level, but other instances should generally be definable in terms of much the same high-level API you'd also use for end applications.

So, I don't really see your concern of don't know instances ⇒ can't hide constructors. If you just define the critical close-to-the-metal instances yourself you should be fine.

That said, I often find it rather annoying if a library doesn't export the constructors at all. Even if every instance and everything else can be defined only using the high-level API, it can make sense to grant unsafe low-level access for a lot of reasons that can't really be forseen. Debugging, special optimisations, simply seeing what's going on...
Hence, in a similar vein to Python's “we're all consenting adults here” philosophy, I'd support kosmikus' suggestion: export the constructors of all important types, but do it in a way that makes it clear that using these directly is unsafe. An extra Unsafe module is a good way to achieve this. Simply giving the constructor a technical-sounding name may also be sufficient. And of course document what precisely is unsafe about these exports.

Upvotes: 5

Related Questions