Search code examples
haskelliomonads

Command line arguments as Ints in Haskell


I have a Haskell program which accepts 2 or 3 Ints from the command line:

-- test.hs

main :: IO ()
main = do
    args <- fmap (read . head) getArgs
    case args of
        [x,y,a] -> doGeneration x y a
        [x,y]   -> doGeneration x y 10
        _       -> usage

However, when I run it with arguments:

$ ./test 100 200
divide: Prelude.read: no parse

Why?


Solution

  • getArgs :: IO [String] returns a list of Strings, by taking the head and then args and it will then read that item.

    You however never specified to what it should read, since you use args in a case … of … clause with [x,y,a] and [x, y], it will try to read it as a list of numbers (the type of the number is specified by the doGeneration signature. This thus means that you should write it as:

    $ ./test [100,200]

    But I think it makes not much sense to do that, you can rewrite the parsing part to:

    main :: IO ()
    main = do
        args <- fmap (map read) getArgs
        case args of
            [x,y,a] -> doGeneration x y a
            [x,y]   -> doGeneration x y 10
            _       -> usage

    This means that it will read every parameter individually, and construct a list with the parsed items, and then we can pattern match on the parsed parts of the program parameters. In that case we thus can still use:

    $ ./test 100 200