基本语法

记录是和代数 data 类型的扩展,允许字段命名:

data StandardType = StandardType String Int Bool --standard way to create a sum type

data RecordType = RecordType { -- the same sum type with record syntax
    aString::String
  , aNumber::Int
  , isTrue  :: Bool
  }

然后可以使用字段名称从记录中获取指定的字段

> let r = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
> :t r
  r::RecordType
> :t aString
  aString::RecordType -> String
> aString r
  "Foobar"

记录可以与模式匹配

case r of
  RecordType{aNumber = x, aString=str} -> ... -- x = 42, str = "Foobar"

请注意,并非所有字段都需要命名

记录是通过命名它们的字段来创建的,但也可以创建为普通的总和类型(当字段数很小且不太可能改变时通常很有用)

r  = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
r' = RecordType  "Foobar" 42 True

如果创建的记录没有命名字段,编译器将发出警告,结果值将为 undefined

> let r = RecordType {aString = "Foobar", aNumber= 42}
  <interactive>:1:9: Warning:
     Fields of RecordType not initialized: isTrue
> isTrue r
  Error 'undefined'

可以通过设置其值来更新记录的字段。未提及的字段不会更改。

> let r = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
> let r' = r{aNumber=117}
    -- r'{aString = "Foobar", aNumber= 117, isTrue = True}

为复杂的记录类型创建镜头通常很有用。