The article gives some examples why smart constructors don't fully solve the problem in the section "Newtypes as tokens"
Re:Names are not type safety
by alexmingoia on Sunday November 01, 2020 @09:45PM
(#24964421)
Yeah, I don’t find those points very convincing. Obviously if you export other ways to construct the type, it doesn’t work...
It’s like saying “if you forget to sanitize input it won’t get sanitized.” Okay?
Re:Names are not type safety
by imoverclocked on Sunday November 01, 2020 @10:04PM
(#24964484)
The entire point of a good type system is to reduce the need for extra cognitive diligence around your data/code. The more corner cases you have to be careful around, the less helpful the type system is.
You have a constructor function which does the input check, and it lives in a module that only exports the smart constructor, not the type constructor. It doesn’t matter if another module deconstructs the type, since the input was already checked.
For example:
newtype Username = Username Text
mkUsername :: Text -> Either Text Username
mkUsername t = if t == “” then Left “Username cannot be blank” else Right (Username t)
If you don’t export the constructor for Username, and only export mkUsername, it doesn’t matter if someone deconstructs the Text from Username, because it must already be validated.