6 ms·
Read the article more carefully. I wrote in multiple places that the use of newtypes does provide real safety. > If you are fond of newtypes, this whole argume
by lexi-lambda 6y ago
Read the article more carefully. I wrote in multiple places that the use of newtypes does provide real safety.
> If you are fond of newtypes, this whole argument may seem a bit troubling. It may seem like I’m implying newtypes are scarcely better than comments, albeit comments that happen to be meaningful to the typechecker. Fortunately, the situation is not quite that grim—newtypes can provide a sort of safety, just a weaker one.
> […]
> This tradeoff may not seem all that bad, and indeed, it is often a very good one! Guaranteeing invariants using constructive data modeling can, in general, be quite difficult, which often makes it impractical.
> […]
> Newtypes are useful when carefully applied
The whole point of the blog post is that newtypes are useful, but only when used in certain ways and in a weaker sense than constructive data modeling.
- carterschonwald 6y agoDefinitely agree the best approach is doing modelling that results in trustworthy / usable coverage checking. ESP since for constrained ranges of values where new type won’t play great with supporting pattern matching without some fancy pattern synonyms. I have seen folks write code that’s like type Name = String rather than use a new type, and I think really new type is about having enforced abstraction over the representation of a datatype, to prevent silent corruptions from transparently equivalent representations that have different meanings. I guess I think it’s good to try to split this sort of opinion piece into a part that’s a forward looking tech challenge along side an exposition that hopefully has clear methodological guidance for today
- platinumrad 6y agoYou say that, on its own, a newtype is nothing more than a name and that names are not type safety, but then you give the example of using newtypes to prevent someone from adding a distance and a duration. I think it's a false distinction to say that the safety there is some kind of safety that isn't type safety.
- lexi-lambda 6y agoYes, on its own, a newtype is nothing more than a name. The safety comes from pairing a newtype with an encapsulation mechanism and a carefully-designed trust boundary. Without an encapsulation mechanism, I do not consider using newtypes to wrap real numbers with units of measure sufficient to be called “type safety”; in my experience it still requires significant discipline to use properly (because the points of wrapping/unwrapping are usually fairly local and require delicate care). Of course, this is a matter of both subjective definition and relative situation. One can theoretically imagine a codebase that conventionally uses units-of-measure wrappers so pervasively that the safety is genuine, since the places where values are wrapped/unwrapped are so well-defined that any misuse would stick out as wrong. However, I have never in my life seen such a codebase, so anecdotally I can only consider such measures more like the lines painted on a road to delineate lanes than a bona fide safety mechanism.
- deleted 6y ago[deleted]
- Joker_vD 6y agoSo basically, "if you don't use newtype to implement an abstract data type, you don't get any type safety because the on-spot wrapping/unwrapping is still possible". On one hand, yes. On another, no. I am working right now on a Go codebase with lots of newtypes (well, the Go's equivalent), and they're generally casted to/from underlying primitive types basically in two places: when they're serialized into JSON, and where they're deserialized from JSON. And in several places in the middle of the code where you need an explicit cast, well, the cast is explicit. You actually have to consider it. Mind you, in Go it's almost impossible to hide the newtype's constructor unless you jump through some rather unintuitive hoops. Is Go fundamentally type-unsafe? I don't think it is, although I sometimes wish some structs were impossible to zero-initialize. Then again, that's generally amended by unexporting the struct and exporting its interface instead.
- codygman 6y ago> Is Go fundamentally type-unsafe? Interface{} and nil pointers point to yes.
- lmm 6y ago> Read the article more carefully. This is unnecessarily rude. Maybe you should have written the article more carefully, or read my comment more carefully. > newtypes are useful, but only when used in certain ways and in a weaker sense than constructive data modeling Constructive data modelling can be an easier way to provide certain kinds of guarantees in some circumstances, perhaps. But the claim that newtype-based approaches are not type safety remains false.
- CyberRabbi 6y agoHmm asking to read something more carefully is not rude if the commenter is refuting a point that was never made in the article.
- quietbritishjim 6y agoIt would suffice to say "that point was not made on the article".
- loup-vaillant 6y agoThat's unnecessarily cautious. Unfounded criticism rightly deserves a slap on the hand, and "Read the article more carefully" is a very light one.
- copascetic 6y agoI think the request is rather justified given your response, which is engaging with a strawman version of the thesis presented in the post. What you wrote about the virtues of newtype was explained quite well in the post itself, but you seem to want to disagree about something. You present another strawman in this reply: > the claim that newtype-based approaches are not type safety To use your phrasing, the claim is that newtypes do not in and of themselves provide type safety, but that "newtype-based approaches" can and do provide a weaker form of safety than constructive modeling. Further, it's important to understand what the critical additional steps are in such approaches to achieving that safety and avoid cargo-culting "newtypes make things type-safe", and to understand the ways this safety can be violated.
- rstarast 6y ago>> I disagree, and I think this kind of fundamentalism hurts the adoption of type safety. For what it's worth, I got a similar impression: An excessively narrow (implied) definition of "type safety", based on which newtype wrappers are criticized, while minimizing or denying the benefit of newtypes over type aliases in preventing errors matching arguments to functions. E.g. the `newtype Email = Email String` example someone mentions down-thread, which has clear benefits as soon as there's a function `sendEmail :: Email -> IO ()`. Benefits that I'd argue many people would be happy to see as part of "type safety".