
On Thu, Jul 3, 2008 at 8:00 PM, Dougal Stanton
Here's a snippet from the parser for one option (others omitted for clarity):
options :: [OptDescr (Opts -> Opts)] options = [ Option "b" ["bus"] (ReqArg busNum "NUM") "Bus number" , ... ] where busNum n os = let b = (query os) { queryBusNumber = Just n } in if isBusId n then os { query = b } else os
Variations on that ugliness are repeated four times for other fields. Is there an alternative way to change the value of nested fields?
Here's one suggestion, though whether it's less ugly is questionable. Start with these two handy TH functions: -- \f x -> x { field = f (field x) } alter :: Name -> Q Exp alter field = do f <- newName "f" x <- newName "x" lamE [varP f, varP x] $ recUpdE (varE x) [return (field, AppE (VarE f) (AppE (VarE field) (VarE x)))] -- \a x -> x { field = a } set :: Name -> Q Exp set field = do a <- newName "a" x <- newName "x" lamE [varP a, varP x] $ recUpdE (varE x) [return (field, VarE a)] Now define busNum as follows: busNum n | (isBusId n) = $(modify 'query) ($(set 'queryBusNumber) (Just n)) | otherwise = id The TH brackets and quotes make it look rather cumbersome, but I think the intent at least becomes clearer. Stuart