2010-01-04 40 views
0

一個簡單的問題,我懷疑。我有簡單的函數定義CAL中的用戶定義記錄類型?

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

其實我是想定義一個新的類型,稱爲

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

這意味着我不必重複記錄結構,所有的時間({名:: String,age :: Int})代替我的代碼如下:

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

這可能嗎?從CAL的角度來看它有意義嗎(它可能不)?

回答

0

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」字段本身發生了什麼,否則這個函數不需要改變。