2010-01-04 7 views
0

Une question simple que je soupçonne. J'ai la simple définition de la fonctionType d'enregistrement défini par l'utilisateur dans CAL?

makePatientFixture :: [ { name :: String, age :: Int} ]; 
makePatientFixture = [ { name = "Dave", age = 41}, { name = "Denise", age = 45}, { name = "Cameron", age = 5} ]; 

Je veux vraiment définir un nouveau type appelé

Patient = { name :: String, age :: Int } 

Cela signifierait que je ne dois pas répéter la structure d'enregistrement tout le temps ({nom :: String, age :: Int}) à la place mon code ressemblerait à:

makePatientFixture :: [ Patient ]; 
makePatientFixture = [ { name = "Dave", age = 41}, { name = "Denise", age = 45}, { name = "Cameron", age = 5} ]; 

Est-ce possible? Cela a-t-il un sens d'un point de vue CAL (ce n'est peut-être pas le cas)?

Répondre

0

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.

Questions connexes