CAL不支持别名(Haskell对'type'关键字支持别名),因此您不能只执行以下操作:
type Patient = {name::String, age::Int}
但是,您可以创建包含记录的新数据类型:
data Patient=
public Patient
details :: {name::String, age::Int}
;
... 然而,这可能不是您需要的。记录对于移动结构化数据位和使用结构化多态性(记录子集的自动投影)非常方便。不过,您不需要像这样存储数据。
相反,我建议:
data Patient=
public Patient
name :: !String
age :: !Int
;
类型上的“plings”表示“不必在这里存储懒散的thunk”,例如,我们确实需要一个字符串和int,即使您将一些复杂的表达式应用于患者构造函数。您可以安全地省略这些扣环,但在大多数情况下,最好将它们包括在内。
现在,您可以使用各种形式的案例分析从此类患者价值中提取元素。您将在手册中看到所有这些,但这里有一个摘要:
age p =
case p of
Patientname age -> age; // Spot the maintenance problem here!
;
nameAndAge p =
case p of
Patient{name,age} -> (name,age); // Now it doesn't matter if the Patient constructor grows new arguments
;
惰性提取器
name p =
let
Patient{name} = p; // name is only extracted (and p partially evaluated) if name is required
in
name;
单箱提取器
name p =
p.Patient.name; // Syntactic sugar for example 1. Useful when you are _only_ extracting a single field.
如果需要,您始终可以从此数据投影记录。
请记住,如果存在多种类型的患者,那么患者数据类型也可以有多个构造函数。
我们可以用以下几条线来表示:
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;
;
事实上,除非构造函数来来去去,或者“patientRecords”字段本身发生了什么事情,否则此函数永远不需要更改。