CAL不支持別名(其中哈斯克爾確實與「型」關鍵字),所以你不能只是做:
type Patient = {name::String, age::Int}
但是,您可以創建一個包含您的記錄中newdata類型:
data Patient=
public Patient
details :: {name::String, age::Int}
;
...但是,這可能不是你所需要的。記錄非常方便,可以移動各種結構化數據並使用結構多態性(自動投影記錄子集)。你不需要像這樣存儲數據。 相反,我建議:
data Patient=
public Patient
name :: !String
age :: !Int
;
的類型意味着「不打擾這裏存儲一個懶惰的thunk」,例如在「plings」即使您將一些複雜的表達式應用於Patient構造函數,我們也確實需要一個字符串和和int。您可以放心地省略圖表,但在大多數情況下包含這些圖表是很好的做法。
您現在可以使用各種形式的案例分析從這樣的Patient值中提取元素。你會看到所有這些手冊中,但這裏有一個總結:
顯性的案例分析,位置匹配:
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.
如果需要,您可以隨時從此數據中投射記錄。 請記住,如果Patient有幾種類型,那麼您也可以擁有Patient數據類型的多個構造函數。
例如,可能有住院患者和門診患者。這兩個共享一些nhs患者記錄,但具有與他們的治療相關的特定領域。 我們可以大致如下表示:
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;
;
這也讓我們來看看一個非常強大的功能,CAL,做多的構造函數匹配。在這種情況下,我們匹配InPatient和OutPatient,僅投影patientRecords字段。
這允許我們編寫一個'nhsRecords'提取器函數,即使Patient構造函數中的細節發生變化,我們也可以很容易地進行維護。
確實,除非構造函數來來去去,或者「patientRecords」字段本身發生了什麼,否則這個函數不需要改變。