0

I am writing a program that should be able to read input either from the command line directly or from a file depending on what args are passed. For example. However I am having trouble making the IO event conditional. My first thought was to do:

import System.Environment

main :: IO ()
main = do
 cla <- getArgs
 let flags = parseFlags (filter isFlag cla) []
 let args  = filter (not.isFlag) cla
 input <- if (elem "e" flags) then (head args) else (readFile (head args))

However this doesn't work because (head args) is not a IO action. My next thought was to do:

import System.Environment

main :: IO ()
main = do
 cla <- getArgs
 let flags = parseFlags (filter isFlag cla) []
 let args  = filter (not.isFlag) cla
 file <- (readFile (head args))
 let input = if (elem "e" flags) then (head args) else (file)

But this will error if the input is not the name of a file. Is there a sensible way to do this? Am I approaching the problem incorrectly?

Wheat Wizard
  • 3,982
  • 14
  • 34
  • 3
    In your first bit of code, the problem actually looks like `(head args)` isn't an IO action, but `(readFile (head args))` is. Youre returning 2 different types. Try just changing `(head args)` to `(return (head args))` to put the value in the IO monad. – Carcigenicate Jun 11 '17 at 15:42
  • @Carcigenicate Thanks! this is exactly what I was looking for. If you would like to post an answer detailing this I would be happy to accept. – Wheat Wizard Jun 11 '17 at 15:45
  • 1
    Unrelated, but how do you know `args` isn't empty? – chepner Jun 11 '17 at 15:49
  • @chepner This code is abbreviated for the sake of clarity. In the code shown I don't, but in my actual code I have more extensive handling, that ensures that the input provided is valid. For the same reason the definition of `parseFlags` has been left out. – Wheat Wizard Jun 11 '17 at 15:51

2 Answers2

4

You were trying to treat (head args) as though it was in the IO monad. Since it's just a raw value, you need to place it into the monad before it can be used as an IO action.

Just change (head args) to (return (head args)).

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
1

You can use return (head args) to lift a type to the IO monad.

ThreeFx
  • 7,250
  • 1
  • 27
  • 51