Re: [Haskell-cafe] GetOpt

2006-05-02 Thread Mirko Rahn

Tomasz Zielonka wrote:


and handle options as functions from Config to Config:



I find this approach very convenient, but I push it a bit further. Some
time ago I wrote a small article about this:



http://www.haskell.org/pipermail/haskell/2004-January/013412.html


[from there]

 -- Here we thread startOptions through all supplied option actions
 opts - foldl (=) (return startOptions) actions

So the order in actions is important and therefore the order of options 
on the commandline is important.


But how to handle dependencies between options using this technique? I 
can image two solutions:
1: Every dependency 'a implies b' has to be checked in both functions, 
the one for a and the one for b.
2: An order for the actions has to be specified, maybe by decorating the 
option list with priorities.


But both solutions seems to be tedious and error prone.

In contrast the sum-type technique first reads all options and then 
post-processes the complete set. Here the order of options on the 
commandline has no impact on the final result.


Regards, Mirko Rahn

--
-- Mirko Rahn -- Tel +49-721 608 7504 --
--- http://liinwww.ira.uka.de/~rahn/ ---
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GetOpt

2006-05-02 Thread Tomasz Zielonka
On Tue, May 02, 2006 at 02:27:28PM +0200, Mirko Rahn wrote:
 But how to handle dependencies between options using this technique? I 
 can image two solutions:
 1: Every dependency 'a implies b' has to be checked in both functions, 
 the one for a and the one for b.
 2: An order for the actions has to be specified, maybe by decorating the 
 option list with priorities.
3: Handle some (not all) options in a sum-type fashion

 In contrast the sum-type technique first reads all options and then 
 post-processes the complete set. Here the order of options on the 
 commandline has no impact on the final result.

I forgot to show that you can still use old style option handling for
some options. This way you can gradually move from sum-type style to
product-type style.

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Tomasz Zielonka
On Thu, Apr 27, 2006 at 02:26:22AM +0300, Einar Karttunen wrote:
 On 26.04 11:29, Anton Kulchitsky wrote:
  I just started to study Haskell and it is my almost first big experience 
  with functional languages (except Emacs Lisp and Python). I enjoyed all 
  small exercises and started a bigger business writing a general utility. 
  However, I have a problem from the beginning. The utility get some file 
  and convert it to another format. It is a kind of small compiler. It 
  also accepts many parameters and behaves depending on them. The problem 
  is how to do this neat! How should I write my program to accept and 
  neatly work with options
 
 One solution is to have a datatype for configuration:
 
  data Config = Config { mode:: Mode,
 infile  :: Maybe FilePath,
 outfile :: Maybe FilePath
   }
  nullConfig = Config Normal - -
  data Mode   = Normal | Version | Help
 
 and handle options as functions from Config to Config:
 
  Option ['i']   [input]   (ReqArg (\x c - c { infile = Just x }) file) 
  input file name

I find this approach very convenient, but I push it a bit further. Some
time ago I wrote a small article about this:

http://www.haskell.org/pipermail/haskell/2004-January/013412.html

I was not the first one to use the approach but I felt that it should be
made more popular. Perhaps I should make a wiki page from it, but I seem
to never do such things and can't promise to do it this time :-/

 and then handle the parsed options like:
 
  case conf of
Config Normal (Just i) (Just o) - ...
Config Normal __- both input and output must be specified
Config Help   __- help message

You can eliminate this pattern matching by using functions and
IO-actions as fields of Config, for example:

 data Config = Config { input   :: IO String, -- or (Handle - IO a) - IO a
output  :: String - IO ()
  }

This way it is easy to read from stdin and write to stdout by default.

We eliminate Version and Help modes by using IO functions as option
handlers, which enables us to finish the execution in the middle of
option processing.

 Option ['h'] [help]   (NoArg (\_ - printHelp  exitWith ExitSuccess)) 
 show help

Your main function could look like this:

 main = do
 args - getArgs
 let (optsActions, rest, errors) = getOpt RequireOrder options args
 mapM_ (hPutStrLn stderr) errors
 config - foldl (=) (return initialConfig) optsActions
 cs - input config
 ...
 output config result

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Mirko Rahn

Tomasz Zielonka wrote:

On Thu, Apr 27, 2006 at 02:26:22AM +0300, Einar Karttunen wrote:



and handle options as functions from Config to Config:


Option ['i']   [input]   (ReqArg (\x c - c { infile = Just x }) file) input 
file name



I find this approach very convenient, but I push it a bit further. Some
time ago I wrote a small article about this:

http://www.haskell.org/pipermail/haskell/2004-January/013412.html

I was not the first one to use the approach but I felt that it should be
made more popular. Perhaps I should make a wiki page from it, but I seem
to never do such things and can't promise to do it this time :-/


You are dealing with more convenient option handling, validating and 
defaulting on top of Sven Pannes famous GetOpt module. Nice stuff but 
there is another important point: Your approach still needs a central 
definition of an option list (or record) in the main (user) program. But 
suppose you write some libraries that are used by a couple of user 
programs. It becomes tedious and error prone to define the same lists of 
options with descriptions and validating functions in all user programs 
just to give it to the library. Moreover the user program in general 
even don't know about the right validating function or option description.


So it would be much better to define the options in the library and to 
provide this definitions to the user program somehow. I tought about 
this topic several times and came up with a solution that works for me 
but is far from being perfect. It uses existentials and a main 
disadvantage is the need of explicit traversing. Moreover some new 
boilerplate code is necessary.


You can find the interface in

http://liinwww.ira.uka.de/~rahn/src/Util/Option.hs

Sample library definitions of options are in

http://liinwww.ira.uka.de/~rahn/src/PCP/Fast/Env.hs
http://liinwww.ira.uka.de/~rahn/src/PCP/Fast/Description.hs

These definitions are combined in

http://liinwww.ira.uka.de/~rahn/src/PCP/Fast/Auto.hs

and finally used for example in the user programs

http://liinwww.ira.uka.de/~rahn/src/Prog/Eval.hs
http://liinwww.ira.uka.de/~rahn/src/Prog/Interesting.hs

Note, that the user programs just define options that are specific for 
the program, e.g. both programs have options to define some search 
bounds without definition.


As stated: Far from being perfect. Looking forward to get some new ideas!

Best regards, Mirko Rahn

--
-- Mirko Rahn -- Tel +49-721 608 7504 --
--- http://liinwww.ira.uka.de/~rahn/ ---
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Bulat Ziganshin
Hello Anton,

Wednesday, April 26, 2006, 11:29:16 PM, you wrote:

 I just started to study Haskell and it is my almost first big experience
 with functional languages (except Emacs Lisp and Python). I enjoyed all
 small exercises and started a bigger business writing a general utility.

you are my ideal client because we both speak Russian (but not here :) )
and both interested in large real-world applications :)  download
the http://freearc.narod.ru/FreeArc-sources.tar.gz and enjoy - it's a
full of Russian comments and it's a real-world program that solves
many problems that you yet foresee :)

in particular, i also started with vision of my program (it's a
RAR-like archiver) as a sequence of transformations:

1) first, a command line translated into the program job - it's
actually business of GetOpt and not very differ from other language's
implementations

2) second, this job plus information about files on disk is translated
into the record of structure of archive being created

3) third, archive structure translated into the sequence of I/O
operations

but when i started to do the actual implementation, i realized that
such pure functional approach is nor appropriate and at the last end
i wrote the straight imperative program, just using the power of
Haskell language. moreover, in this process i added to the language
many imperative constructs that make imperative programming easier

 However, I have a problem from the beginning. The utility get some file
 and convert it to another format. It is a kind of small compiler. It 
 also accepts many parameters and behaves depending on them. The problem
 is how to do this neat! How should I write my program to accept and 
 neatly work with options

you can see my solution in Cmdline module - it's one of largest module
in my program. i don't like the GetOpt interface (it returns a list of
options what is unusable for high-speed application) so i implemented
my own option-processing routines, it's just about 50 lines long
(great demonstration of Haskell power!). all processed options are
record in one large record that is passed around all the program. if
you get accustomed to global variables, it's using in Haskell is
possible but that is not the best way. you can also use implicit
parameters (at least in hugs and ghc), but this again makes data
dependencies somewhat non-understandable

btw, i suggest you to use WinHugs for debugging program and ghc for
final compilation. this makes faster development time together with
faster final executable. moreover, making your program compatible with
both environments is almost ensure that it will be compatible with
coming Haskell standard, Haskell-prime

returning back to options parsing - there is an interesting
alternative to GetOpt (which is just mimics corresponding C module) -
it's a PescoCmd:

http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-2.0.tgz
http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-2.0.pdf
http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-man-2.0.pdf

i also recommend you to read several other real-world Haskell program
where you can steal more code and ideas:

http://postmaster.cryp.to/postmaster-2005-02-14.tar.gz
ftp://ftp.cse.unsw.edu.au/pub/users/dons/yi/yi-0.1.0.tar.gz
darcs (darcs get --partial http://www.abridgegame.org/repos/darcs/)
happs (darcs get --partial http://happs.org/HAppS)

and one more interesting source of real-world approach to Haskell
programming:

http://www.haskell.org/haskellwiki/Hitchhikers_Guide_to_the_Haskell


-- 
Best regards,
 Bulatmailto:[EMAIL PROTECTED]

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Tomasz Zielonka
On Thu, Apr 27, 2006 at 03:10:32PM +0400, Bulat Ziganshin wrote:
 i don't like the GetOpt interface (it returns a list of options what
 is unusable for high-speed application)

This got me interested. I assume that you measured performace and it
wasn't fast enough.

How many command line args you had to handle? How many options? I don't
know how well System.GetOpt works with many possible options. It doesn't
seem to use any sophisticated algorithm for searching options, so the
cost of getOpt can be proportional to N*M, where N = numer of option
descriptions, M = number of program args.

If this was improved, it might become usable for you.

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Einar Karttunen
On 27.04 12:32, Mirko Rahn wrote:
 So it would be much better to define the options in the library and to 
 provide this definitions to the user program somehow. I tought about 
 this topic several times and came up with a solution that works for me 
 but is far from being perfect. It uses existentials and a main 
 disadvantage is the need of explicit traversing. Moreover some new 
 boilerplate code is necessary.

HAppS has a typeclass for this kind of thing also:

http://test.happs.org/auto/apidoc/HAppS-Util-StdMain-Config.html
http://test.happs.org/HAppS/src/HAppS/Util/StdMain/Config.hs

and for an example instance see:

http://test.happs.org/HAppS/src/HAppS/Protocols/SimpleHTTP.hs

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Anton Kulchitsky



I find this approach very convenient, but I push it a bit further. Some
time ago I wrote a small article about this:

http://www.haskell.org/pipermail/haskell/2004-January/013412.html

I was not the first one to use the approach but I felt that it should be
made more popular. Perhaps I should make a wiki page from it, but I seem
to never do such things and can't promise to do it this time :-/

  

Thank you so much!!! That is great!

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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread Anton Kulchitsky

Hi Bulat,

thank you very much for such a detailed reply!


I just started to study Haskell and it is my almost first big experience
with functional languages (except Emacs Lisp and Python). I enjoyed all
small exercises and started a bigger business writing a general utility.



you are my ideal client because we both speak Russian (but not here :) )
  

Da! :) Spasibo.


and both interested in large real-world applications :)  download
the http://freearc.narod.ru/FreeArc-sources.tar.gz and enjoy - it's a
full of Russian comments and it's a real-world program that solves
many problems that you yet foresee :)

in particular, i also started with vision of my program (it's a
RAR-like archiver) as a sequence of transformations:

1) first, a command line translated into the program job - it's
actually business of GetOpt and not very differ from other language's
implementations

2) second, this job plus information about files on disk is translated
into the record of structure of archive being created

3) third, archive structure translated into the sequence of I/O
operations

but when i started to do the actual implementation, i realized that
such pure functional approach is nor appropriate and at the last end
i wrote the straight imperative program, just using the power of
Haskell language. moreover, in this process i added to the language
many imperative constructs that make imperative programming easier

  
I really trying to avoid imperative approach. I do have a terribly big 
experience in imperative programming (by the way, you might know one 
application that I made about 3 years ago. It is Uni-K Sensei for 
windows). Now, I am breaking my previous habits just to think wider and 
more effective.

However, I have a problem from the beginning. The utility get some file
and convert it to another format. It is a kind of small compiler. It 
also accepts many parameters and behaves depending on them. The problem
is how to do this neat! How should I write my program to accept and 
neatly work with options



you can see my solution in Cmdline module - it's one of largest module
in my program. i don't like the GetOpt interface (it returns a list of
options what is unusable for high-speed application) so i implemented
  
Well, I do not care too much about high-speed. My main goal is to write 
a prototype of the language that I am creating. It is a kind of 
Domain-Specific language. I decided to start from a simple thing. A 
converter of pgn files with chess notation to javascript to visualize 
it. Just to have some practice.

my own option-processing routines, it's just about 50 lines long
(great demonstration of Haskell power!). all processed options are
record in one large record that is passed around all the program. if
you get accustomed to global variables, it's using in Haskell is
possible but that is not the best way. you can also use implicit
parameters (at least in hugs and ghc), but this again makes data
dependencies somewhat non-understandable

  
Thank you very much. I will see this approach as well. I am still pretty 
concern of using records instead of lists.



btw, i suggest you to use WinHugs for debugging program and ghc for
final compilation. this makes faster development time together with
faster final executable. moreover, making your program compatible with
both environments is almost ensure that it will be compatible with
coming Haskell standard, Haskell-prime
  
Thanks again. I do not use Windows any more. I use Mac or different 
Unices. I do use ghc everywhere I work with Haskell. For debugging I use 
ghci. Well, and everything within GNU Emacs.



returning back to options parsing - there is an interesting
alternative to GetOpt (which is just mimics corresponding C module) -
it's a PescoCmd:

http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-2.0.tgz
http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-2.0.pdf
http://scannedinavian.org/~pesco/distfiles/pesco-cmdline-man-2.0.pdf

  

Thanks! Very interesting


i also recommend you to read several other real-world Haskell program
where you can steal more code and ideas:

http://postmaster.cryp.to/postmaster-2005-02-14.tar.gz
ftp://ftp.cse.unsw.edu.au/pub/users/dons/yi/yi-0.1.0.tar.gz
darcs (darcs get --partial http://www.abridgegame.org/repos/darcs/)
happs (darcs get --partial http://happs.org/HAppS)
  

Darcs was a little too complicated for me. Thank you for other links.


and one more interesting source of real-world approach to Haskell
programming:

http://www.haskell.org/haskellwiki/Hitchhikers_Guide_to_the_Haskell


  
Thank you very much, Bulat. Now I see why people say that haskell-cafe 
is the best mail-list! :)


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


Re: [Haskell-cafe] GetOpt

2006-04-27 Thread John Meacham
I wrote an option parser that infers everything about the options from
the types of what you pull out of it so there is no need to specify
redundant information and you can write very concise code (especially when 
combined with
the overloaded regex module!)

like for instance

main = do
 (args,(verb,output_name)) - getOptions (v|verbose, o)
 putStrLn $ if verb then verbose mode else not verbose
 case output_name of
Nothing - putStrLn no output
Just fn - putStrLn $ output file is:  ++ fn

will just work, infering from the type that '-v' and '-verbose' are
simple flags, while '-o' takes a string argument.


you can even set help messages with the (??) operator

o ?? output file name

and default values with the (==) operator.

o == out.txt

it can be gotten here:
http://repetae.net/john/recent/out/GetOptions.html
and help is at:
http://repetae.net/john/recent/src/hsdocs//GetOptions.html

John


-- 
John Meacham - ⑆repetae.net⑆john⑈
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] GetOpt

2006-04-26 Thread Einar Karttunen
On 26.04 11:29, Anton Kulchitsky wrote:
 I just started to study Haskell and it is my almost first big experience 
 with functional languages (except Emacs Lisp and Python). I enjoyed all 
 small exercises and started a bigger business writing a general utility. 
 However, I have a problem from the beginning. The utility get some file 
 and convert it to another format. It is a kind of small compiler. It 
 also accepts many parameters and behaves depending on them. The problem 
 is how to do this neat! How should I write my program to accept and 
 neatly work with options

One solution is to have a datatype for configuration:

 data Config = Config { mode:: Mode,
infile  :: Maybe FilePath,
outfile :: Maybe FilePath
  }
 nullConfig = Config Normal - -
 data Mode   = Normal | Version | Help

and handle options as functions from Config to Config:

 Option ['i']   [input]   (ReqArg (\x c - c { infile = Just x }) file) 
 input file name

and then handle the parsed options like:

 case conf of
   Config Normal (Just i) (Just o) - ...
   Config Normal __- both input and output must be specified
   Config Help   __- help message

- Einar Karttunen

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