Search code examples
haskellcommand-line-argumentshaskell-platform

Parsing a CSV list from command line argument in Haskell


I have a program that takes some command lines arguments.

Say the first command line argument is a comma separated value (CSV) list of integers.

I want to convert the first argument "1,2,4,8,16" to [1,2,4,8,16]. I attempted to parse the the string into an Int list but I got a compile error.

Haskell Code:

import System.Environment
import Data.List
import Text.Regex

main = do
  args <- getArgs

  ints <- if   (length args > 1)
          then (mapM read (splitRegex (mkRegex ",") (args!!1)))
          else [1,3,5] -- defaults
  print (ints)

Compile Error:

myProg.hs:10:16:
    Couldn't match expected type `IO' with actual type `[]'
    In the expression: [1, 3, 5]
    In a stmt of a 'do' block:
      ints <- if (length args > 1) then
                  (mapM read (splitRegex (mkRegex ",") (args !! 1)))
              else
                  [1, 3, 5]
    In the expression:
      do { args <- getArgs;
           ints <- if (length args > 1) then
                       (mapM read (splitRegex (mkRegex ",") (args !! 1)))
                   else
                       [1, ....];
           print (ints) }

I am unsure what this type error means. I would greatly appreciate it if someone could explain the type error to me and how to modify my code to achieve the desired result.


Solution

  • You don't want to use <- to define ints because you're not executing an IO action in there. You can just use a let binding. That also lets you replace the call to mapM with a plain map.

    The first proper argument is also indexed at 0, rather than 1 like you might see in C. You can use head to get at that as well.

    let ints = if   length args >= 1
               then map read (splitRegex (mkRegex ",") (head args))
               else [1, 3, 5]