简体   繁体   中英

Idiomatic way to conditionally process IO in Haskell

I'm writing a little shell script in Haskell which can take an optional argument. However, if the argument is not present, I'd like to get a line from stdin in which to ask for a value.

What would be the idiomatic way to do this in Haskell?

#!/usr/bin/env runhaskell

import Control.Applicative ((<$>))
import Data.Char (toLower)
import IO (hFlush, stdout)
import System.Environment (getArgs)

main :: IO ()
main = do args <- getArgs
          -- here should be some sort of branching logic that reads
          -- the prompt unless `length args == 1`
          name <- lowerCase <$> readPrompt "Gimme arg: "
          putStrLn name

lowerCase = map toLower

flushString :: String -> IO ()
flushString s = putStr s >> hFlush stdout

readPrompt :: String -> IO String
readPrompt prompt = flushString prompt >> getLine

Oh, and if there's a way to do it with something from Control.Applicative or Control.Arrow I'd like to know. I've become quite keen on these two modules.

Thanks!

main :: IO ()
main = do args <- getArgs
          name <- lowerCase <$> case args of
            [arg] -> return arg
            _     -> readPrompt "Gimme arg: "
          putStrLn name

This doesn't fit your specific use case, but the question title made me think immediately of when from Control.Monad . Straight from the docs :

when :: Monad m => Bool -> m () -> m ()

Conditional execution of monadic expressions.

Example:

main = do args <- getArgs
          -- arg <- something like what FUZxxl did..
          when (length args == 1) (putStrLn $ "Using command line arg: " ++ arg)
          -- continue using arg...

You can also use when 's cousin unless in similar fashion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM