开发者

When should I use record syntax for data declarations in Haskell?

开发者 https://www.devze.com 2022-12-13 01:40 出处:网络
Record synt开发者_如何学Pythonax seems extremely convenient compared to having to write your own accessor functions. I\'ve never seen anyone give any guidelines as to when it\'s best to use record syn

Record synt开发者_如何学Pythonax seems extremely convenient compared to having to write your own accessor functions. I've never seen anyone give any guidelines as to when it's best to use record syntax over normal data declaration syntax, so I'll just ask here.


You should use record syntax in two situations:

  1. The type has many fields
  2. The type declaration gives no clue about its intended layout

For instance a Point type can be simply declared as:

data Point = Point Int Int deriving (Show)

It is obvious that the first Int denotes the x coordinate and the second stands for y. But the case with the following type declaration is different (taken from Learn You a Haskell for Great Good):

data Person = Person String String Int Float String String deriving (Show) 

The intended type layout is: first name, last name, age, height, phone number, and favorite ice-cream flavor. But this is not evident in the above declaration. Record syntax comes handy here:

data Person = Person { firstName :: String  
                     , lastName :: String  
                     , age :: Int  
                     , height :: Float  
                     , phoneNumber :: String  
                     , flavor :: String  
                     } deriving (Show)   

The record syntax made the code more readable, and saved a great deal of typing by automatically defining all the accessor functions for us!


In addition to complex multi-fielded data, newtypes are often defined with record syntax. In either of these cases, there aren't really any downsides to using record syntax, but in the case of sum types, record accessors usually don't make sense. For example:

data Either a b = Left { getLeft :: a } | Right { getRight :: b }

is valid, but the accessor functions are partial – it is an error to write getLeft (Right "banana"). For that reason, such accessors are generally speaking discouraged; something like getLeft :: Either a b -> Maybe a would be more common, and that would have to be defined manually. However, note that accessors can share names:

data Item = Food { description :: String, tastiness :: Integer }
    | Wand { description :: String, magic :: Integer }

Now description is total, although tastiness and magic both still aren't.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号