2010-05-28 6 views
5

Je reçois l'entrée (x) de l'utilisateur, la convertit en Int par let y = (read x) :: Int et je voudrais que la fonction se comporte d'une manière spéciale si l'utilisateur ne donne rien (vide chaîne).Valeur NILL dans 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 

Merci pour l'aide, Bye

Répondre

3

Il n'y a pas NULL sauf si vous définissez explicitement. Vous pouvez vérifier les chaînes vides comme ceci.

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 fonction 'read' ne peut pas convertir une chaîne vide en int, et provoquera une erreur si vous essayez de le faire. Vous devrez tester si l'entrée est une chaîne vide avant convertissant en int. Si vous souhaitez utiliser une valeur par défaut (par exemple 0) dans le cas où l'utilisateur entre une chaîne vide, vous pouvez faire quelque chose comme ceci:

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

S'il vous plaît, n'enseignez pas les personnes 'longueur x == 0'. La façon idiomatique et performante d'écrire ce test est «null x». –

+1

Quant à être idiomatique, point pris. Compte tenu de la définition de «longueur», je ne peux pas croire qu'il y aurait une différence dans perf. En tout cas, je suis un peu surpris que quelqu'un ait ressenti le besoin de voter. –

+4

"length" marchera jusqu'à la fin de la chaîne afin de trouver la longueur, et si cette chaîne est 400203209 caractères, vous avez un problème de performance. "null" fonctionnera à temps constant, car il suffit de voir si au moins un élément est là. – LukeN

14

Peut-être que vous voulez un type Maybe? Si l'utilisateur entre la chaîne vide, votre fonction renvoie Nothing; sinon, il renvoie Just n, où n est ce que saisit l'utilisateur?

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

(je ne l'ai pas compilé ce code.)

4

Dans ce cas, Maybe peut ne pas suffire: Vous avez trois conditions à se soucier:

  1. L'utilisateur est entré rien
  2. L'entrée de l'utilisateur était valide
  3. La saisie de l'utilisateur était impossible

Ce type de données et la fonction expriment ceci directement:

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 

Notez que plutôt que d'utiliser la fonction incomplète read, il utilise reads qui ne sera pas erreur sur l'entrée qui ne peut pas être converti. reads a une interface un peu maladroite, hélas, donc je finis presque toujours par l'emballer dans une fonction qui renvoie Maybe a ou quelque chose comme ça ici.

Exemple d'utilisation:

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

je coder votre fonction yearFilter comme ceci:

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

Ensuite, je poignée d'entrée utilisateur comme:

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 : J'ai nettoyé le code dans yearFilter un peu: pas besoin d'utiliser des gardes pour produire un booléen à partir d'un test - juste retourner le test, l'application de fonction (objectYear) se lie plus étroitement que les opérateurs (==) parenthèse enlevé, remplacé les noms des entrées inutilisées par _.


D'accord, je l'avoue, je ne peux pas me aider .... Je l'ai réécrite yearFilter encore une fois, cette fois-ci que je serais enclin à écrire:

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

Apprendre Maybe et maybe était la première chose à propos de Haskell qui m'a vraiment fait aimer la langue.