Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using getArgs or user input

New to Haskell and wrestling with a problem. I know why my code doesn't work, but I cannot figure out the solution.

The intention is for the user to provide a file name either via argument or, if none provided, prompt the user to enter the data. A message with the file name is printed to the screen and the file is processed.

import System.Environment
main = do
    args <- getArgs
    let file = if null args
        then do putStr "File: " ; getLine
        else head args
    putStr "processing"
    putStrLn file
    writeFile file "some very nice text"

The code is wrong, of course, but demonstrates the logic I've been wrestling with. Neither Happy Learn Haskell nor Learn you Haskell could put me over the hump. The closest thread I could find was this one. Many thanks for assistance.

like image 876
Bill Avatar asked Mar 09 '26 02:03

Bill


1 Answers

Let us analyze the type of file:

let file = if null args
    then do putStr "File: " ; getLine
    else head args

Here the if-then-else statement has as condition null args, which is indeed a Bool, so we are safe. But the the then part has as type IO String. So Haskell reasons that args should be an [IO String], but it is not: it is a list of Strings, so [String].

Later another problem pops up: you use file as a String, but it is not: it is still an IO String.

There are a few ways to fix it. Probably the minimal change is to use pure to wrap the head args back into an IO, and use replace the let clause with a <- statement:

import System.Environment

main = do
    args <- getArgs
    file <- if null args
        then do putStr "File: " ; getLine
        else pure (head args)
    putStr "processing "
    putStrLn file
    writeFile file "some very nice text"
like image 113
Willem Van Onsem Avatar answered Mar 10 '26 23:03

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!