
Hi all, I was wondering if there is syntactic sugar in Haskell for defining a default value for fields in a data type. For instance, say I have a type that is defined in record syntax: type CustomerID = Int type Address = Maybe String data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show) Is there any way to define default values for some (or all) fields such that they may be omitted from a declaration, and still have it generate a valid object? e.g.) a = Customer{customerID = 12, customerName="Bill"} -- I would like a{customerAddress} to default to Nothing (for instance). It seems to me that this would be a nice feature to have, if it does not exist. Am I missing something? Mike

On Mon, Sep 22, 2008 at 02:38:32PM -0500, Mike Sullivan wrote:
Hi all,
I was wondering if there is syntactic sugar in Haskell for defining a default value for fields in a data type. For instance, say I have a type that is defined in record syntax:
type CustomerID = Int type Address = Maybe String
data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show)
Is there any way to define default values for some (or all) fields such that they may be omitted from a declaration, and still have it generate a valid object?
e.g.) a = Customer{customerID = 12, customerName="Bill"} -- I would like a{customerAddress} to default to Nothing (for instance).
It seems to me that this would be a nice feature to have, if it does not exist. Am I missing something?
Hi Mike, This feature doesn't exist, but it is easy to code it yourself by creating a record with default values in it: defaultCust = Customer 0 "" Nothing Then instead of saying a = Customer{...}, you can say a = defaultCust{customerID = 12, customerName="Bill"} and the remaining field will default to Nothing, since that field of defaultCust was not overridden. -Brent

On 2008 Sep 22, at 15:38, Mike Sullivan wrote:
I was wondering if there is syntactic sugar in Haskell for defining a default value for fields in a data type. For instance, say I have a type that is defined in record syntax: type CustomerID = Int type Address = Maybe String data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show) Is there any way to define default values for some (or all) fields such that they may be omitted from a declaration, and still have it generate a valid object?
e.g.) a = Customer{customerID = 12, customerName="Bill"} -- I would like a{customerAddress} to default to Nothing (for instance).
It seems to me that this would be a nice feature to have, if it does not exist. Am I missing something?
aCustomer = Customer { customerAddress = Nothing } -- ... a = aCustomer { customerID = 12, customerName = "Bill" } This will net you a compile time warning about uninitialized fields in aCustomer, and if you fail to initialize a Customer properly it will produce a runtime error: *Main> customerName b "*** Exception: fooo.hs:6:12-49: Missing field in record construction Main.customerName You will *not* get a warning for missing values in variables initialized this way, only for the special initializer value. I'm not sure if it's possible to make the type system handle this, but if it is then it'll probably be painful and ugly. (Now watch someone post an elegant one-liner....) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Hi Brent and Brandon, Thank you for responding! Okay, so from the responses it seems that it's simple to define a "datatype" (partially applied function, really) which has "default" parameters for all fields. Or, using the same method, for the first N fields (N is less than or equal to the number of fields): defaultCust = Customer 0 "" -- for instance, building upon Brent's example However, it's not quite so easy to pick and choose (define only the name, for instance). I guess this really isn't too much of a limitation, since a simple function could set any defaults you want: defaultCust2 id addr = Customer id "Bill" addr -- function which simulates a default value for "name" So despite the lack of syntactic sugar, the simplicity and power of functions can make do. One down side, however, is that you lose the flexibility of record syntax (unless there is an analogue for functions that I don't know about). Mike On Tue, Sep 23, 2008 at 11:25 PM, Brandon S. Allbery KF8NH < allbery@ece.cmu.edu> wrote:
On 2008 Sep 22, at 15:38, Mike Sullivan wrote:
I was wondering if there is syntactic sugar in Haskell for defining a default value for fields in a data type. For instance, say I have a type that is defined in record syntax:
type CustomerID = Int type Address = Maybe String
data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show)
Is there any way to define default values for some (or all) fields such that they may be omitted from a declaration, and still have it generate a valid object?
e.g.) a = Customer{customerID = 12, customerName="Bill"} -- I would like a{customerAddress} to default to Nothing (for instance).
It seems to me that this would be a nice feature to have, if it does not exist. Am I missing something?
aCustomer = Customer { customerAddress = Nothing } -- ... a = aCustomer { customerID = 12, customerName = "Bill" }
This will net you a compile time warning about uninitialized fields in aCustomer, and if you fail to initialize a Customer properly it will produce a runtime error:
*Main> customerName b "*** Exception: fooo.hs:6:12-49: Missing field in record construction Main.customerName
You will *not* get a warning for missing values in variables initialized this way, only for the special initializer value. I'm not sure if it's possible to make the type system handle this, but if it is then it'll probably be painful and ugly. (Now watch someone post an elegant one-liner....)
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On 2008 Sep 24, at 21:38, Mike Sullivan wrote:
defaultCust2 id addr = Customer id "Bill" addr -- function which simulates a default value for "name"
So despite the lack of syntactic sugar, the simplicity and power of functions can make do. One down side, however, is that you lose the flexibility of record syntax (unless there is an analogue for functions that I don't know about).
*Main> aCustomer{customerName = "Bob", customerID = 9} Customer {customerID = 9, customerName = "Bob", customerAddress = Nothing} *Main> a{customerName = "Bob", customerID = 9} Customer {customerID = 9, customerName = "Bob", customerAddress = Nothing} assuming "aCustomer" and "a" from my previous message: aCustomer is the custom initializer and a is a value initialized from it. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Wed, Sep 24, 2008 at 9:02 PM, Daniel Fischer
On 2008 Sep 24, at 21:38, Mike Sullivan wrote:
defaultCust2 id addr = Customer id "Bill" addr -- function which simulates a default value for "name"
So despite the lack of syntactic sugar, the simplicity and power of functions can make do. One down side, however, is that you lose the flexibility of record syntax (unless there is an analogue for functions that I don't know about).
*Main> aCustomer{customerName = "Bob", customerID = 9} Customer {customerID = 9, customerName = "Bob", customerAddress = Nothing} *Main> a{customerName = "Bob", customerID = 9} Customer {customerID = 9, customerName = "Bob", customerAddress = Nothing}
assuming "aCustomer" and "a" from my previous message: aCustomer is the custom initializer and a is a value initialized from it.
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Am Donnerstag, 25. September 2008 03:38 schrieb Mike Sullivan:
Hi Brent and Brandon,
Thank you for responding! Okay, so from the responses it seems that it's simple to define a "datatype" (partially applied function, really) which has "default" parameters for all fields. Or, using the same method, for the first N fields (N is less than or equal to the number of fields):
defaultCust = Customer 0 "" -- for instance, building upon Brent's example
However, it's not quite so easy to pick and choose (define only the name, for instance). I guess this really isn't too much of a limitation, since a simple function could set any defaults you want:
defaultCust2 id addr = Customer id "Bill" addr -- function which simulates a default value for "name"
So despite the lack of syntactic sugar, the simplicity and power of functions can make do. One down side, however, is that you lose the flexibility of record syntax (unless there is an analogue for functions that I don't know about).
Why would you lose the record syntax? With type CustomerID = Int type Address = Maybe String data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show) you define your default customer cust = Customer{ customerID=0, customerName="", customerAddress=Nothing } and then just create your customers like a = cust{customerID=12, customerName="Bill" } -- a === Customer 12 "Bill" Nothing b = cust{ customerID=13, customerName="Gordon",customerAddress=Just "10 Downing Street" } -- b === Customer 13 "Gordon" (Just "10 Downing Street") using cust as a smart constructor (to make sure no customers with uninitialized fields are created, don't export the data constructor Customer, only cust and the fields)
Mike
On Tue, Sep 23, 2008 at 11:25 PM, Brandon S. Allbery KF8NH <
allbery@ece.cmu.edu> wrote:
On 2008 Sep 22, at 15:38, Mike Sullivan wrote:
I was wondering if there is syntactic sugar in Haskell for defining a default value for fields in a data type. For instance, say I have a type that is defined in record syntax:
type CustomerID = Int type Address = Maybe String
data Customer = Customer { customerID :: CustomerID , customerName :: String , customerAddress :: Address } deriving (Show)
Is there any way to define default values for some (or all) fields such that they may be omitted from a declaration, and still have it generate a valid object?
e.g.) a = Customer{customerID = 12, customerName="Bill"} -- I would like a{customerAddress} to default to Nothing (for instance).
It seems to me that this would be a nice feature to have, if it does not exist. Am I missing something?
aCustomer = Customer { customerAddress = Nothing } -- ... a = aCustomer { customerID = 12, customerName = "Bill" }
This will net you a compile time warning about uninitialized fields in aCustomer, and if you fail to initialize a Customer properly it will produce a runtime error:
*Main> customerName b "*** Exception: fooo.hs:6:12-49: Missing field in record construction Main.customerName
You will *not* get a warning for missing values in variables initialized this way, only for the special initializer value. I'm not sure if it's possible to make the type system handle this, but if it is then it'll probably be painful and ugly. (Now watch someone post an elegant one-liner....)
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (4)
-
Brandon S. Allbery KF8NH
-
Brent Yorgey
-
Daniel Fischer
-
Mike Sullivan