}
parseConfig = runConfigParser $ do
server <- readString "server"
port <- readInt "port"
return ParsedConfig{..} -- record wild card
If the "server" attribute is not available in the input, readString "server" will return an error value, but it will return. Thus, when the ParsedConfig is constructed, it will contain holes if there are any errors. But errors are logged separately, and will be reported before the ParsedConfig is used in the application.
This isn't as semantically nice as the applicative approach (suppose you try to do conditional logic on an attribute, but it's an error value), but it's convenient because you can use RecordWildCards to gather up the attributes without repeating their names. I suppose you could still do this and use ApplicativeDo, but it's not available yet (or is it?)