|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
Alternatives to convoluted record syntaxHi Haskellers,
This is a style question, as my program works fine but looks really ugly and can be confusing to maintain. I take options from the command line using GetOpt and hand back this structure for later use. > data Opts = Opts > { query :: Query > , queryLimit :: Maybe Limit > , disabledOnly :: Bool > } deriving Show 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? Thanks, Dougal. -- Dougal Stanton dougal@... // http://www.dougalstanton.net _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
|
Re: Alternatives to convoluted record syntaxOn Thu, 3 Jul 2008, Dougal Stanton wrote: > 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? For access to nested record fields I implemented the record-access package. Unfortunately the field accessors must still be written manually. http://darcs.haskell.org/record-access/src/Data/Accessor/Example.hs E.g.: infix2 :: ((Char, Int), String) infix2 = (('b',7),"hallo")$%first^:second^=10 (second^=10) replaces the second member of pair with a value. (^:) applies that change to the outer record (again a pair). ($%) applies the modifier (first^:second^=10) to a concrete pair. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
|
Re: Alternatives to convoluted record syntaxOn Thu, Jul 3, 2008 at 11:13 AM, Henning Thielemann
<lemming@...> wrote: > > infix2 :: ((Char, Int), String) > infix2 = > (('b',7),"hallo")$%first^:second^=10 > > (second^=10) replaces the second member of pair with a value. > (^:) applies that change to the outer record (again a pair). > ($%) applies the modifier (first^:second^=10) to a concrete pair. > Hmm! Thanks for the pointer, but I'm not sure that would really clear things up much. It seems this may just be a wart I'll have to put up with. Cheers, D -- Dougal Stanton dougal@... // http://www.dougalstanton.net _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
|
Re: Alternatives to convoluted record syntaxOn Thu, Jul 3, 2008 at 8:00 PM, Dougal Stanton <dougal@...> wrote:
> 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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
|
Re: Alternatives to convoluted record syntax> For access to nested record fields I implemented the record-access > package. Unfortunately the field accessors must still be written manually. > http://darcs.haskell.org/record-access/src/Data/Accessor/Example.hs I looked for this on hackage, but found instead this: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/data-accessor which, unless I am mistaken, is actually a different package by Luke Palmer, with similar intent. Should we be trying to avoid name overlaps like this? Tim _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
|
|
Re: Alternatives to convoluted record syntaxHi,
> busNum n > | (isBusId n) = $(modify 'query) ($(set 'queryBusNumber) (Just n)) > | otherwise = id > The solution I am using is creating for each record type @Rec@, and each of its fields @fieldName :: T@ an updater updateFieldName :: (T -> T) -> Rec -> Rec This way you can write busNum n | (isBusId n) = updateQuery $ updateQueryBusNumber $ const (Just n) | otherwise = id The task of creating updaters can be automated using TH, this is what the attached library does: all you need is to say $(genUpdaters ''Opts) $(genUpdaters ''Query) Cheers, Misha _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@... http://www.haskell.org/mailman/listinfo/haskell-cafe |
| Free Forum Powered by Nabble | Forum Help |