I am looking at this example using getOpts, and one portion of it really baffles me: the syntax of field labels.
First, this seems simple enough, creating a data type and declaring the initial values:
data Options = Options { optVerbose :: Bool
, optInput :: IO String
, optOutput :: String -> IO ()
}
startOptions :: Options
startOptions = Options { optVerbose = False
, optInput = getContents
, optOutput = putStr
}
Then getOpt is used to go through the options and determine the actual parameters for the running program using a foldl command... and then this let expression frustrates me:
let Options { optVerbose = verbose
, optInput = input
, optOutput = output } = opts
The boolean and functions verbose, input, and output are then used after this. In most of the programming languages I'm more familiar with, this step would be written something like so:
verbose = opts.optVerbose
input = opts.optInput
output = opts.optOutput
Is Haskell's behavior here documented someplace?
It's just normal pattern-matching — just like when you write let (x:xs) = someList and it assigns the first element to x and the rest of the list to xs.
If you wanted, you could write:
let verbose = optVerbose opts
input = optInput opts
output = optOutput opts
Pattern-matching is everywhere in Haskell and the ML family, but not as common in other languages.
This is standard Haskell syntax for defining, setting, and getting values of/from data type defined using records. For instance, in the record
data R a = R {v :: a,
f :: a -> a}
a value of type R a can be created, given a value x :: a and a function g :: a -> a, by
r = R {v = x, f = g}
Values of fields can be accessed in the following way:
get_v :: R a -> a
get_v = v
get_f :: R a -> a -> a
get_f = f,
I.e., get_f = f and get_v = v. Values can be set in a similar manner, using curly brackets:
set_v :: R a -> a -> R a
set_v r a = r {v = a}
set_f :: R a -> (a -> a) -> R a
set_f r g = r {f = g}
I.e., set_v and set_f are identical to
record {field = value}
where field is the automatically generated function Haskell provides for access to a record field, and value is the desired value. The values of fields in a data type defined using records can be accessed and set using these operations. The let expression in your example is creating a value of type Options and setting the values of its fields.
(I'm pretty sure I'm not wrong about this, but if I am...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With