3 ms·
The way to ensure type safety of new types is smart constructors: https://wiki.haskell.org/Smart_constructors https://wiki.haskell.org/Smart_constructors You h
by alexmingoia 6y ago
The way to ensure type safety of new types is smart constructors: https://wiki.haskell.org/Smart_constructors https://wiki.haskell.org/Smart_constructors
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.
- shawnz 6y agoThe article gives some examples why smart constructors don't fully solve the problem in the section "Newtypes as tokens"
- alexmingoia 6y agoYeah, 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?
- imoverclocked 6y agoThe 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.
- deleted 6y ago[deleted]
- remexre 6y agoI've gotten bit by the Generic one in real code before... I'm sure if I used Haskell for RESTful web stuff more, I'd eventually get bit by something similar for Aeson too.