Re: [Haskell-cafe] Avoiding boilerplate retrieving GetOpt cmd line args

2007-07-27 Thread Andrea Rossato
On Thu, Jul 26, 2007 at 10:25:06PM -0700, 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 

I don't know if my reply is going to be helpful to you. This is what I
would suggest: why don't you create a data type with label records,
and than you store that data type in a IORef and update the IORef. At
the end you just read the IORef with your updated data:

data Config = { filter :: String
  , dateFormat :: String
  , etc ...
  } 

Then you create a new IOref with config, and, with getOpt, you update
the IOref with modifyIORef. At the very end you read the modified
IOref.

This way you can have default options to be modified with command line
options.

I don't know if it is clear, but I adopted this approach in a program
I'm writing. A program with 14 command line options.

Have a look at this part here (starting from data Opts=):
http://gorgias.mine.nu/repos/xmobar/Main.hs

This way I can load a configuration file and change some of the
options, configured in that file, with the given command line options.

I hope this is going to help you.
Andrea
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Avoiding boilerplate retrieving GetOpt cmd line args

2007-07-27 Thread Neil Mitchell
Hi

Why not:

 data Flag
   = Filter String
   | DateFormat String
   | DocStart String
   | DocEnd String

Becomes:

data Flag = Flag Key String
data Key = Filter | DateFormat | DocStart | DocEnd

getString :: Flag - Key - String
getString (Flag x y) key = if key == x then y else 

You can easily extend this to defaults:

defaults = [(DocStart,1)]

then lookup, instead of just  as the else clause.

If you have to use Data/Typeable you will no longer be writing
portable Haskell, and while they are great, they aren't the thing to
use here.

Thanks

Neil
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Avoiding boilerplate retrieving GetOpt cmd line args

2007-07-27 Thread Jonathan Cast
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


[Haskell-cafe] Avoiding boilerplate retrieving GetOpt cmd line args

2007-07-26 Thread Dave Bayer
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?

Thanks,
Dave

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Avoiding boilerplate retrieving GetOpt cmd line args

2007-07-26 Thread Levi Stephen

Hi,

Not sure if this will help avoid the boilerplate, but I've always liked 
the approach at 
http://leiffrenzel.de/papers/commandline-options-in-haskell.html 
(particularly the section Towards a higher level) for being able to 
specify defaults. It's the best resource I've found on command line 
options in Haskell so far.


Levi
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?

Thanks,
Dave

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe