Types with a single data constructor can be defined in the following style, in which case they are called record types.
type Song = {title : Text, artist : Text, year : Nat}
A type like this has field names assigned to each argument of the type constructor, meaning it can be inspected or modified like this:
track13 = Song "Yesterday" "The Beatles" 1965
Song.title track13⧨"Yesterday"
use Text ++
track13 = Song "Yesterday" "The Beatles" 1965
Song.title.modify (yesterday -> yesterday ++ "(Remastered)") track13
|> Song.year.set 2009⧨Song "Yesterday(Remastered)" "The Beatles" 2009
Compare this to a regular type declaration with unnamed arguments:
type Point = Point Nat Nat
The arguments have no name, so they are only identified positionally.
The effect of creating a record type is to generate some accessor methods, to help get, set, and modify each field.
Song.title : Song -> Text
Song.title.modify : (Text ->{g} Text) -> Song ->{g} Song
Song.title.set : Text -> Song -> Song
There's currently no special syntax for creating, pattern matching, or decomposing records. That works the same as for regular data types: