2011-04-21 13 views
7

Estoy escribiendo un pequeño script de shell en Haskell que puede tomar un argumento opcional. Sin embargo, si el argumento no está presente, me gustaría obtener una línea de stdin para pedir un valor.Forma idiomática de procesar condicionalmente IO en Haskell

¿Cuál sería la forma idiomática de hacer esto en 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 

Ah, y si hay una manera de hacerlo con algo de Control.Applicative o Control.Arrow me gustaría saber. Me he entusiasmado con estos dos módulos.

Gracias!

Respuesta

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

Me gusta. Está bastante limpio. Los patrones en la expresión de casos no son exhaustivos, pero se pueden corregir fácilmente. –

+0

@ Ionuţ G. Stan: Simplemente traduzco tu significado uno por uno. Hacer el patrón exhaustivo haría que mi ejemplo fuera menos limpio. – fuz

+0

Pondría 'lowerCase <$>' delante de 'case args of' para que la línea de comando arg también se ponga en minúscula. Además, podría hacer coincidir '[arg]' y '_' (en lugar de' [] ') para estar más cerca del comportamiento solicitado. –

1

Esto no encaja en el caso de uso específico, pero el título de la pregunta me hizo pensar inmediatamente en when de Control.Monad. Directamente desde the docs:

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

ejecución condicional de expresiones monádicos.

Ejemplo:

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

También puede utilizar primo unlesswhen 's de manera similar.

+0

Pensé en 'cuándo' también. El problema era que necesitaba algún tipo de it/then/else en lugar de solo un if/then. Además, cuando no devuelve nada. Hubiera tenido que "asignarle una variable" dentro, lo que probablemente significa usar la mónada de estado. Aunque no estoy tan seguro Gracias por la respuesta. –

Cuestiones relacionadas