Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refactor duplicate field names in Haskell data types?

Tags:

haskell

I'm trying to write a data structure that describes items on my CV, just to learn about Haskell and its data types. Here's what I have so far:

data Update = Talk { date :: Date,
                     pubTitle :: Text,
                     url :: URI,
                     venue :: Text
                   }
            | Publication { date :: Date,
                            pubTitle :: Text,
                            venue :: Venue,
                            pubType :: PublicationType
                          }
            | Award { date :: Date,
                      award :: Text,
                      awardedBy :: Link
                    }
            | News { date :: Date, desc :: Markdown }
            deriving Show


data PublicationType = Tutorial | Article | Chapter | Abstract

This won't work, apparently, since Haskell thinks I have multiple declarations of date and so on. I've seen this question where an answer suggests using an extension, but I tried adding {-# LANGUAGE DuplicateRecordFields #-} to the top of my file, and it doesn't seem to help—I'm getting the same errors.

I suspect that there's a way to refactor these records in some way, no? Or maybe I should be doing something different entirely to convey this kind of data structure.

like image 755
Jonathan Avatar asked Jan 13 '20 18:01

Jonathan


1 Answers

One approach you could take would be to factor out the duplication:

data Update = Update Date Event                                                 

data Event = News Markdown                                                      
           | Award Text Link                                                    
           | Artifact { title :: Text                                           
                      , venue :: Venue                                          
                      , artifact :: Accomplishment                              
                      }                                                         

data Accomplishment = Talk URI                                                  
                    | Publication PublicationType

Here I've used record syntax for the Artifact constructor, but I'm not convinced it's the best approach. The partial accessors it creates are pretty gross; I just used it because it's otherwise not clear what the Text field means. You could clear this up using non-record syntax by defining a newtype around Text, or a type alias; or you could add a named Artifact type that contains the same thing, with the Artifact constructor just holding an Artifact.

like image 118
amalloy Avatar answered Nov 15 '22 07:11

amalloy