Search code examples
haskellrecord

How do I set default values in a record


I'm trying to set default values in a record object that can be overwritten.

data Car c y = Car {
    company :: c,
    year :: y
    }

What I'd like to do is set a default:

data Car c y = Car {
    company :: c -- OR "Ford"
    year :: y
    }

So far I've tried doing this by setting the type of c to a Maybe type:

data Car = Car {
    company:: Maybe String
    year :: Maybe Int
    }

However I get this predictable error:

Fields of `Car' not initialised: year

Ironically, this is exactly the thing I'm trying to get around. I want to produce a new record that has the values I'm not setting already initialized. One way I've found is to partially apply the Car type:

data Car c y = {
    company :: c,
    year :: y
    }

let ford = Car "Ford" 

-- This produces a function (y -> Car [Char] y)

However this produces 2 new problems:

  1. In the event my data type has 100+ field types, I'll end up with 100 factorial curried functions

  2. The partially applied functions I can create are dependent on the order of variables in the declaration. You'll notice that I cant produce a car1988 function, for example.

How can I write a function that allows me to create records with default values? Please help.


Solution

  • That's the kind of thing Haskell prefers to handle in a library, rather than hacking up some hard-wired language support (which would probably cause all kinds of problems, just like it does in C++).

    import Data.Default
    
    instance Default Car where
      def = Car Nothing Nothing
              -- or whatever you want as the defaults
    
    ford :: Car
    ford = def { company = Just "Ford" }
    

    GHCi> ford
    Car {company = Just "Ford", year = Nothing}

    Rather than using the Default class you can also just define a defaultCar.

    You may need to use cabal to install data-default, if it's not installed in your system already.