开发者

Haskell command line options

I've written a basic head emulator that reads from stdIn:

import IO
import System

io lineList = interact (unlines . lineList . lines)
--Found this. Basically it takes all input from stdIn and reads it lazily.
main = do
    [numLines] <- getArgs
    io (take (read numLines))
    --reads by lines.

And then I attempted to add command lines like so (source: http://leiffrenzel.de/papers/commandline-options-in-haskell.html)

import IO
import System
import System.Console.GetOpt

io lineList = interact (unlines . lineList . lines)
--Found this. Basically it takes all input from stdIn and reads it lazily.
main = do
    args <- getArgs
    let ( actions, nonOpts, msgs ) = getOpt     RequireOrder     options args
    opts <- foldl (>>=) (return defaultOptions) actions
    let Options {   optNum = input,
                    optOut = output} = opts
    input >>= output

data Options = Options {
        optNum :: IO String,
        optOut :: String -> IO ()
    }

defaultOptions :: Options
defaultOptions = Options {
        optNum = "10",
        optOut = io (take optNum)
    }

options :: [OptDescr (Options -> IO Options)]
options = [
    Option ['n'] ["numlines"] (OptArg readNumLines     )    "read x amount of lines"
    ]

readNumLines arg opt = return opt (go arg)
go w = io (take (read w))
    --reads by lines.

Now, my experience here is running out. It seems like the only place I'm actually calling readNumL开发者_如何学JAVAines is from the Options, if the N switch is set. Now, if the N switch is not set, I want to run the readNumLines command with an arg of 10. I'm obviously not doing this right.

Thanks in advance :)

EDIT: So, after a bit of trolling my code, I've got it to a state where it doesn't throw any errors at me, but still won't compile: Not in scope: data constructor 'options', but I've defined options already? EDIT: I had changed the Options constructor, but now it's telling me that it can't match the expected type of IO Options with the actual type Options at the opts <- foldl (>>=) (return defaultOptions) actions

I tried removing actions but that didn't work.

EDIT: So I removed most of that problematic line, and it worked.

opts <- return defaultOptions

However, passing -n doesn't do anything, it only returns the top 10 lines.


Let's go over what the body of main should do.

Read command-line arguments:
args <- getArgs

Parse the arguments:
let ( actions, nonOpts, msgs ) = getOpt RequireOrder options args

Combine the arguments into a set of program parameters:
opts <- foldl (>>=) (return defaultOptions) actions

Extract parameters:
let Options { optNum = input, optOut = output} = opts

Use the parameters:
input >>= output

The GetOpt library only deals with parsing command-line arguments. In your case, the only thing command line arguments can control is the number of lines of output, so the Options data structure should only contain the number of lines of output. There's no point in encoding it as a string, you can just use an int.

data Options = Options { optNum :: Int }

When you specify a command-line option, an ArgDescr is used to specify the parser for the option's argument. The parser takes a string and turns it into a program-specific data structure. What you want is to turn a string into a function that updates an Options value. Note that I took out the IO type (you don't need IO), which will require some minor changes elsewhere in your code.

readNumLines :: String -> Options -> Options
readNumLines n options = options {optNum = read n}

After parsing options, the default options are updated as directed by each command-line argument (remember, parsing produces functions that update an Options value), to generate the final options. You're using IO to do this step, but you really don't need to.
opts <- foldl (>>=) (return defaultOptions) actions

Since the fields of Options have changed, the option-extracting code in main has to be updated to
let Options { optNum = opt_num } = opts

At this point, you have a variable that holds the actual number of lines of code that should be printed, based on the command line options, and you can do whatever you want with it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜