Reputation: 29789
I get input (x) from user, convert it to Int by let y = (read x)::Int and then I would like the function to behave in a special way if user gave nothing (empty string).
-- 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
Thanks for help, Bye
Upvotes: 5
Views: 6184
Reputation: 5150
In this case, Maybe
may not suffice: You have three conditions to worry about:
This data type and function express this directly:
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
Note that rather than using the incomplete function read
, it uses reads
which will not error on input which cannot be converted. reads
has a somewhat awkward interface, alas, so I almost always end up wrapping it in a function that returns Maybe a
or something like this here.
Example use:
> input "42" :: Input Int
Input 42
> input "cat" :: Input Int
BadInput "cat"
> input "" :: Input Int
NoInput
I would code your yearFilter
function like this:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter Nothing _ = True
yearFilter (Just x) y = x == objectYear y
Then I'd handle user input as:
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) ....
N.B.: I've cleaned up the code in yearFilter
a bit: no need to use guards to produce a boolean from a test - just return the test, function application (objectYear
) binds tighter than operators (==
) so removed parenthesis, replaced names of unused inputs with _
.
Okay, I admit I can't help myself.... I've rewritten yearFilter
yet again, this time as I would be inclined to write it:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter x y = maybe True (== objectYear y) x
Learning about Maybe
and maybe
was first thing about Haskell that really made me love the language.
Upvotes: 4
Reputation: 202725
Perhaps you want a Maybe
type? If the user enters the empty string, your function returns Nothing
; otherwise it returns Just n
, where n
is what's entered by the user?
userInt :: String -> Maybe Int
userInt [] = Nothing
userInt s = Just $ read s
(I haven't compiled this code.)
Upvotes: 14
Reputation: 12077
The 'read' function cannot convert an empty string to an int, and will cause an error if you try to do so. You'll need to test whether the input is an empty string before converting to int. If you want to use a default value (such as 0) in the event that the user enters an empty string, you could do something like this:
let y = if null x then 0 else read x
Upvotes: 2
Reputation: 5722
There is no NULL unless you explicitly define it. You could check for empty strings like this.
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"
Upvotes: 3