On Friday 27 July 2007, Dave Bayer wrote: > Ok, I'm writing a command line tool, using System.Console.GetOpt to > handle command line arguments. My Flags structure so far is > > > data Flag > > = Filter String > > > > | DateFormat String > > | DocStart String > > | DocEnd String > > ... > > and I want to write accessor functions that return the strings if > specified, otherwise returning a default. The best I've been able to > > do is this: > > getFilter = getString f "Markdown.pl" > > where f (Filter s) = Just s > > f _ = Nothing > > > > getDateFormat = getString f "%B %e, %Y" > > where f (DateFormat s) = Just s > > f _ = Nothing > > > > getDocStart = getString f "^{-$" > > where f (DocStart s) = Just s > > f _ = Nothing > > > > getDocEnd = getString f "^-}$" > > where f (DocEnd s) = Just s > > f _ = Nothing > > using a generic accessor function `getString`. > > There are eight (and growing) needless lines here, where what I > really want to do is to pass the constructors `Filter`, `DateFormat`, > `DocStart`, or `DocEnd` to the function `getString`. ghci types each > of these as `String -> Flag`, so one at least knows how to type such > a `getString`, but using a constructor-passed-as-an-argument in a > pattern match is of course a "Parse error in pattern". (I expected as > much, but I had to try... `String -> Flag` is not enough information > to make it clear we're passing a constructor, rather than some hairy > arbitrary function, so such a pattern match would be undecidable in > general.) > > So what's the right idiom for avoiding this boilerplate?
What you want can (almost) be done as follows: {-# OPTIONS_GHC -fglasgow-exts #-} import Data.Generics import Data.Typeable data Flag = Filter String | DateFormat String | DocStart String | DocEnd String deriving (Typeable, Data) getString :: Flag -> String -> Flag -> String getString c df f | toConstr c /= toConstr f = df getString c df (Filter s) = s getString c df (DateFormat s) = s getString c df (DocStart s) = s getString c df (DocEnd s) = s This version uses overlapping patterns, of course; it should be evident how to change that if you want. Call it as getString Filter{} "Markdown.pl" flag Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs
pgp7JvE0fRdTA.pgp
Description: PGP signature
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe