Les principaux usages des newtypes sont:
- Pour définir différentes instances de types.
- De la Documentation.
- Données/format de l'exactitude de l'assurance.
Je suis en train de travailler sur une application dès maintenant dans lequel j'utilise newtypes largement. newtypes
en Haskell sont purement moment de la compilation concept. E. g. avec unwrappers ci-dessous, unFilename (Filename "x")
compilés dans le même code "x". Il n'y a absolument zéro au moment de l'exécution de frapper. Il est avec data
types. Cela en fait un bon moyen d'atteindre les objectifs énumérés ci-dessus.
-- | A file name (not a file path).
newtype Filename = Filename { unFilename :: String }
deriving (Show,Eq)
Je ne veux pas accidentellement traiter cela comme un chemin de fichier. Ce n'est pas un chemin d'accès au fichier. C'est le nom d'un modèle conceptuel de fichier quelque part dans la base de données.
Il est très important pour les algorithmes à se référer au droit chose, newtypes aider avec ceci. Il est aussi très important pour la sécurité, par exemple, envisager d'envoyer des fichiers d'une application web. J'ai ces types:
-- | A sanitized (safe) filename.
newtype SanitizedFilename =
SanitizedFilename { unSafe :: String } deriving Show
-- | Unique, sanitized filename.
newtype UniqueFilename =
UniqueFilename { unUnique :: SanitizedFilename } deriving Show
-- | An uploaded file.
data File = File {
file_name :: String -- ^ Uploaded file.
,file_location :: UniqueFilename -- ^ Saved location.
,file_type :: String -- ^ File type.
} deriving (Show)
Supposons que j'ai cette fonction qui nettoie un nom de fichier à partir d'un fichier qui a été téléchargé:
-- | Sanitize a filename for saving to upload directory.
sanitizeFilename :: String -- ^ Arbitrary filename.
-> SanitizedFilename -- ^ Sanitized filename.
sanitizeFilename = SanitizedFilename . filter ok where
ok c = isDigit c || isLetter c || elem c "-_."
Maintenant depuis que je génère un nom de fichier unique:
-- | Generate a unique filename.
uniqueFilename :: SanitizedFilename -- ^ Sanitized filename.
-> IO UniqueFilename -- ^ Unique filename.
C'est dangereux pour générer un nom de fichier unique à partir d'un nom de fichier arbitraire, il doit être désinfecté en premier. De même, un nom de fichier unique est donc toujours en sécurité par extension. Je peux enregistrer le fichier sur le disque maintenant et de mettre le nom du fichier dans ma base de données si je veux.
Mais il peut aussi être gênant d'avoir à enrouler/dérouler beaucoup. Dans le long terme, je vois qu'il vaut en particulier pour éviter de valeur différences. ViewPatterns aider un peu:
-- | Get the form fields for a form.
formFields :: ConferenceId -> Controller [Field]
formFields (unConferenceId -> cid) = getFields where
... code using cid ..
Peut-être que vous allez dire que déballer dans une fonction est un problème: que faire si vous passez cid
pour une fonction à tort? Pas de problème, toutes les fonctions à l'aide d'un id de la conférence sera l'utilisation de la ConferenceId type. Ce qui émerge est une sorte de fonction-fonction de niveau système de contrat qui est forcé au moment de la compilation. Assez agréable. Donc oui je l'utilise aussi souvent que je peux, en particulier dans les grands systèmes.