Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using record syntax with algebraic data types with multiple constructors

The following data type is a representation of a phosphatidic acid (PA - a subclass of lipid). Using mass spectrometry, there are different levels of structural detail that may be acquired (i.e., from simply knowing the mass of the lipid all the way to having a full structural characterisation).

I currently have the PA data type as-

data PA   = ClassLevelPA       IntegerMass
          | CombinedRadylsPA   CombinedRadyls
          | UnknownSnPA        Radyl Radyl
          | KnownSnPA          { paSn1 :: Radyl
                               , paSn2 :: Radyl }
          deriving (Show, Eq, Ord)

This combines constructors with record syntax with those that don't (possibly a bad idea). Alternatively, I could do one of the following -

data PA   = ClassLevelPA       { paIntegerMass :: IntegerMass }
          | CombinedRadylsPA   { paCombinedRadyls :: CombinedRadyls }
          | UnknownSnPA        { paR1 :: Radyl 
                               , paR2 :: Radyl }
          | KnownSnPA          { paSn1 :: Radyl
                               , paSn2 :: Radyl }

data PA   = ClassLevelPA       IntegerMass
          | CombinedRadylsPA   CombinedRadyls
          | UnknownSnPA        Radyl Radyl
          | KnownSnPA          Radyl Radyl

I am not currently using the accessor functions paSn1 and paSn2 but my current thinking is that they could be useful later on. The later alternative is much cleaner though and and also avoids having to deal with multiply field names for different records (until the OverloadedRecordFields extension is added to GHC). Of the three representations, which one is preferable and what is the stance on using constructors with record syntax with those that don't?

like image 591
Michael T Avatar asked Oct 22 '15 03:10

Michael T


1 Answers

Using accessor functions for datatypes with more than one constructor is widely discouraged, because these functions will be partial. I would think you could probably do better using prisms and/or traversals from the lens package. Prisms provide a lensy alternative to pattern matching and constructor application. Traversals (more to the point) let you deal with zero or more things, including fields that may or may not be there. The magic Template Haskell functions for making the traversals will, I believe) require you to include accessors (with names that start with _), but you never need to use those directly or export them.

like image 200
dfeuer Avatar answered Oct 15 '22 10:10

dfeuer