2010-05-28 13 views
5

Obtengo la entrada (x) del usuario, la convierto en Int por let y = (read x) :: Int y luego me gustaría que la función se comporte de una manera especial si el usuario no dio nada (vacío cuerda).Valor NILL en haskell

-- In this place I would like to handle situation in which user 
-- gave empty string as argument 
-- this doesnt work :/ 
yearFilter [] y = True 

--This works fine as far as y is integer 
yearFilter x y | x == (objectYear y) = True 
       | otherwise = False 

Gracias por la ayuda, Bye

Respuesta

3

No hay NULL a menos que se defina explícitamente. Puede verificar cadenas vacías como esta.

readInput :: IO() 
readInput = do 
    ln <- getLine 
    if valid ln 
     then -- whatever 
     else -- whatever 

valid x 
    | null x    = False 
    | not istJust convert x = False 
    | otherwise    = True 
where convert :: String -> Maybe Int 
     convert = fmap fst $ listToMaybe . reads $ "f" 
2

La función 'leer' no puede convertir una cadena vacía en un int, y provocará un error si lo intentas. Deberá probar si la entrada es una cadena vacía antes de convertir a int. Si desea utilizar un valor predeterminado (por ejemplo, 0) en el caso de que el usuario introduce una cadena vacía, se podría hacer algo como esto:

let y = if null x then 0 else read x 
+4

Por favor, no enseñe a las personas 'longitud x == 0'. La forma idiomática y performante de escribir esta prueba es 'null x'. –

+1

En cuanto a ser idiomático, punto tomado. Dada la definición de 'longitud', no puedo creer que haya alguna diferencia en perf. En cualquier caso, estoy un poco sorprendido de que alguien haya sentido la necesidad de votar. –

+4

"longitud" recorrerá la cadena hasta el final para averiguar la longitud, y si esa cadena tiene 400203209 caracteres, tiene un problema de rendimiento. "nulo" se ejecutará en tiempo constante, porque solo necesita ver si hay al menos UN elemento ahí. – LukeN

14

Tal vez usted quiere un tipo Maybe? Si el usuario ingresa la cadena vacía, su función devuelve Nothing; de lo contrario, devuelve Just n, donde n es lo que ingresa el usuario?

userInt :: String -> Maybe Int 
userInt [] = Nothing 
userInt s = Just $ read s 

(no he compilado este código.)

4

En este caso, Maybe puede no ser suficiente: Usted tiene tres condiciones de las que preocuparse:

  1. El usuario introduce nada
  2. La entrada del usuario era válida
  3. La entrada del usuario no se pudo analizar

Este tipo de datos y la función expresan esta directamente:

data Input a = NoInput | Input a | BadInput String 
    deriving (Eq, Show) 

input :: (Read a) => String -> Input a 
input "" = NoInput 
input s = 
    case filter (null.snd) (reads s) of 
     ((a,_):_) -> Input a 
     otherwise -> BadInput s 

Tenga en cuenta que en lugar de utilizar la función incompleta read, utiliza reads que no error en la entrada que no se pueden convertir. reads tiene una interfaz algo incómoda, por desgracia, así que casi siempre termino envolviéndolo en una función que devuelve Maybe a o algo así aquí.

Ejemplo del uso:

> input "42" :: Input Int 
Input 42 
> input "cat" :: Input Int 
BadInput "cat" 
> input "" :: Input Int 
NoInput 

que sería el código de su función yearFilter así:

yearFilter :: Maybe Int -> Int -> Bool 
yearFilter Nothing _ = True 
yearFilter (Just x) y = x == objectYear y 

entonces yo manejar la entrada de usuario como:

inputToMaybe :: Input a -> Maybe a 
inputToMaybe (Input a) = Just a 
inputToMaybe _   = Nothing 

do 
    a <- input `fmap` getLine 
    case a of 
     BadInput s -> putStrLn ("Didn't understand " ++ show s) 
     otherwise -> ... yearFilter (inputToMaybe a) .... 

NB : He limpiado el código en yearFilter un poco: no hay necesidad de usar guardias para producir un booleano de una prueba - simplemente devuelva la prueba, la aplicación de función (objectYear) se une más estrechamente que los operadores (==) para quitar los paréntesis, reemplazó los nombres de las entradas no utilizadas con _.


De acuerdo, admito que no puedo ayudar yo .... Yo he reescrito yearFilter una vez más, esta vez como me inclinaría a escribirlo:

yearFilter :: Maybe Int -> Int -> Bool 
yearFilter x y = maybe True (== objectYear y) x 

Aprender sobre Maybe y maybe fue lo primero sobre Haskell que realmente me hizo amar el lenguaje.