代码之家  ›  专栏  ›  技术社区  ›  David Collie

CAL中的用户定义记录类型?

  •  0
  • David Collie  · 技术社区  · 16 年前

    我怀疑这是一个简单的问题。我有一个简单的函数定义

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

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

    这意味着我不必一直重复记录结构({name::String,age::Int}),相反,我的代码如下所示:

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

    这可能吗?从CAL的角度来看,它有意义吗(可能没有)?

    1 回复  |  直到 16 年前
        1
  •  0
  •   David Collie    16 年前

    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”字段本身发生了什么事情,否则此函数永远不需要更改。

    推荐文章