CAL ne supporte pas aliasing (qui Haskell fait avec le mot-clé 'de type'), de sorte que vous ne pouvez pas le faire:
type Patient = {name::String, age::Int}
Cependant, vous pouvez créer un type newdata qui intègre votre dossier:
data Patient=
public Patient
details :: {name::String, age::Int}
;
... Cependant, ce n'est probablement pas ce dont vous avez besoin. Les enregistrements sont très utiles pour déplacer des bits de données structurées et utiliser un polymorphisme structurel (projection automatique de sous-ensembles d'enregistrements). Vous n'avez pas besoin de stocker les données comme ça. Au lieu de cela, je vous recommande:
data Patient=
public Patient
name :: !String
age :: !Int
;
Les « plings » sur les types signifient « ne dérange pas le stockage d'un thunk paresseux ici », par exemple nous voulons vraiment une chaîne et un int même si vous appliquez une expression compliquée au constructeur Patient. Vous pouvez sans risque omettre les plis, mais c'est une bonne pratique de les inclure dans la plupart des cas.
Vous pouvez maintenant utiliser différentes formes d'analyse de cas pour extraire des éléments d'une telle valeur Patient. Vous verrez tout cela dans le manuel, mais voici un résumé:
analyse Overt cas, correspondance de position:
age p =
case p of
Patientname age -> age; // Spot the maintenance problem here!
;
analyse Overt cas, match de symbole:
nameAndAge p =
case p of
Patient{name,age} -> (name,age); // Now it doesn't matter if the Patient constructor grows new arguments
;
extracteur Lazy
name p =
let
Patient{name} = p; // name is only extracted (and p partially evaluated) if name is required
in
name;
Extracteur de caisse unique
name p =
p.Patient.name; // Syntactic sugar for example 1. Useful when you are _only_ extracting a single field.
Vous pouvez toujours projeter un enregistrement à partir de ces données si nécessaire. Rappelez-vous que vous pouvez également avoir plusieurs constructeurs pour le type de données Patient, s'il y a plusieurs types de Patient.
Par exemple, il y a peut-être des patients hospitalisés et des patients externes. Les deux partagent certains dossiers de patients nhs, mais ont des champs spécifiques pertinents pour leur traitement. Nous pourrions représenter le long des lignes suivantes:
data Patient=
public InPatient
patientRecords :: !PatientRecord
careCentreID :: !Int
department :: !String
consultant :: !String
| publicOutPatient
patientRecords :: !PatientRecord
appointments :: ![Appointment]
;
nhsRecords p =
case p of
(InPatient|OutPatient) {patientRecords} -> patientRecords;
;
Cela nous permet également de regarder une fonction CAL très puissant qui fait correspondant constructeur multiples. Dans ce cas, nous comparons InPatient et OutPatient, en ne projetant que le champ patientRecords.
Cela nous permet d'écrire une fonction d'extraction « nhsRecords » que nous pouvons maintenir assez facilement même que les détails du changement des constructeurs de patients.
En effet, sauf si les constructeurs vont et viennent, ou que quelque chose arrive au champ "patientRecords" lui-même, cette fonction n'a jamais besoin de changer.