Hello there,
I've been thinking on different approaches to constraint particular functions to a particular constructor of an ADT in order to reduce representation of invalid states. Say for example I've this types:
data Address = Address { ... }
newtype Email = Email String
data Package = Package { ... }
data EmailMsg = EmailMsg { ... }
data User
= RealUser Address
| VirtualUser Email
And I would like to implement two functions:
deliverPackage :: User -> Package -> IO Bool
sendEmail :: User -> EmailMsg -> IO ()
I would like to constraint both deliverPackage and sendEmail to receive only the semantically correct constructor of User.
I know of an approach I could use, that is wrapping each constructor in it's own newtype, and create some smart constructor that way, that approach works, but I find it rather verbose.
Is there any other well known approach to deal with this scenarios?