Je me demande ce qui est mieux en termes de conception pour l'utilisabilité / la maintenabilité, et ce qui est mieux en ce qui concerne la communauté.
Étant donné le modèle de données:
type Name = String
data Amount = Out | Some | Enough | Plenty deriving (Show, Eq)
data Container = Container Name deriving (Show, Eq)
data Category = Category Name deriving (Show, Eq)
data Store = Store Name [Category] deriving (Show, Eq)
data Item = Item Name Container Category Amount Store deriving Show
instance Eq (Item) where
(==) i1 i2 = (getItemName i1) == (getItemName i2)
data User = User Name [Container] [Category] [Store] [Item] deriving Show
instance Eq (User) where
(==) u1 u2 = (getName u1) == (getName u2)
Je peux implémenter des fonctions monadiques pour transformer l'utilisateur par exemple en ajoutant des articles ou des magasins, etc., mais je peux me retrouver avec un utilisateur invalide, donc ces fonctions monadiques devraient valider l'utilisateur qu'elles obtiennent et / ou créent.
Alors, devrais-je juste:
- envelopper dans une monade d'erreur et faire exécuter les fonctions monadiques à la validation
- envelopper dans une monade d'erreur et obliger le consommateur à lier une fonction de validation monadique dans la séquence qui génère la réponse d'erreur appropriée (afin qu'ils puissent choisir de ne pas valider et transporter un objet utilisateur non valide)
- en fait, construisez-le dans une instance de liaison sur l'utilisateur créant efficacement mon propre type de monade d'erreur qui exécute la validation avec chaque liaison automatiquement
Je peux voir les points positifs et négatifs de chacune des 3 approches, mais je veux savoir ce qui est plus couramment fait pour ce scénario par la communauté.
Donc, en termes de code, quelque chose comme, option 1:
addStore s (User n1 c1 c2 s1 i1) = validate $ User n1 c1 c2 (s:s1) i1
updateUsersTable $ someUser >>= addStore $ Store "yay" ["category that doesnt exist, invalid argh"]
Option 2:
addStore s (User n1 c1 c2 s1 i1) = Right $ User n1 c1 c2 (s:s1) i1
updateUsersTable $ Right someUser >>= addStore $ Store "yay" ["category that doesnt exist, invalid argh"] >>= validate
-- in this choice, the validation could be pushed off to last possible moment (like inside updateUsersTable before db gets updated)
option 3:
data ValidUser u = ValidUser u | InvalidUser u
instance Monad ValidUser where
(>>=) (ValidUser u) f = case return u of (ValidUser x) -> return f x; (InvalidUser y) -> return y
(>>=) (InvalidUser u) f = InvalidUser u
return u = validate u
addStore (Store s, User u, ValidUser vu) => s -> u -> vu
addStore s (User n1 c1 c2 s1 i1) = return $ User n1 c1 c2 (s:s1) i1
updateUsersTable $ someValidUser >>= addStore $ Store "yay" ["category that doesnt exist, invalid argh"]