I don't know how to check type of variable in haskell, Here i mean , when i read something from console with getLine ,however i expect it to be an interger but user can enter a string also,then i don't want my program to crash. For example if someone inputs a string and i try to convert it to Int then it will crash(exception) so i want to check whether it is convertable or not. How do i do that ? Thanks for any help :)
main1 = do
let g <- getLine
k = g :: Int
if(k :: Int)
then ........
EDIT: Notice you always have a string from getLine - that's the type it returns. If that string contains an ascii representation of a number then great and keep reading.
If you have a string, g, and say g :: Int the compiler will simply so "no, you are wrong, that's a String". You need to perform a translation - parse the string and compute an Int. The most readily available methods are read in the Prelude and readMaybe in Text.Read.
Read will work but throws exceptions on invalid input:
Prelude> read "4742" :: Int
4742
Prelude> read "no" :: Int
*** Exception: Prelude.read: no parse
Prelude> read "191andmore"
*** Exception: Prelude.read: no parse
The maybe variant is exception safe:
Prelude> import Text.Read
Prelude Text.Read> readMaybe "181" :: Maybe Int
Just 181
Prelude Text.Read> readMaybe "no" :: Maybe Int
Nothing
Prelude Text.Read> readMaybe "211andmore" :: Maybe Int
Nothing
Related
The only "user input" functions I know of in the Prelude return Strings - but often (I'd say more frequently) we want to read numbers or other types.
Is there a function of type :: IO a or similar, for reading a value of arbitrary type? I've searched hoogle for such a function, but either due to it not existing or due to the large number of other functions of similar type, I've not found anything.
It seems useful and simple enough that there must be a built-in. The closest I've come is this:
-- Eg.
get :: Read a => IO a
get = (liftM read) getLine
main = do
x <- get
print $ x + 5
There's readLn:
readLn :: Read a => IO a
Worth noting that readLn calls readIO in order to raise an IO exception instead of undefined.
Prelude> x <- (fmap read getLine) :: IO Integer
asdf
Prelude> x
*** Exception: Prelude.read: no parse
Prelude> x <- (readIO =<< getLine) :: IO Integer
asdf
*** Exception: user error (Prelude.readIO: no parse)
I want to read a string from keyboard but i don't know why isn't working, I tried a lot of methods, but nothing worked! Can someone help me or give me an idea?
type Polinom = [Int]
scriePolinom :: Polinom -> String
....
main = do
a<-getLine
--let a=[2,-5,1]
scriePolinom a
Parse the line into the corresponding data:
import Data.List
parseIntList :: String -> [Int]
parseIntList s = [read x :: Int | x <- words s]
type Polinom = [Int]
scriePolinom :: Polinom -> String
....
main = do
a <- getLine
let intlist = parseIntList a
putStrLn $ scriePolinom intlist
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :type getLine -- you can also write :t getLine
getLine :: IO String
This tells you that getLine always gives you (after doing some kind of impure I/O operations, in this case waiting for the user to enter some stuff on the keyboard, until pressing enter) a value of type String. Which makes sense: a string, also called...
Prelude> :info String -- you can also write :i String
type String = [Char] -- Defined in ‘GHC.Base’
...list of characters. These are just the exact characters/keys the user typed in. In general, these characters may not properly describe a Polinom – what, for example, if the user enters 34958oiyq4ulbwre?
What you need to do is trying to parse the input string to a more meaningfully-typed value, like Polinom. How to do that depends on what form you actually expect the input to be. If the user should use normal Haskell syntax for the coefficients, e.g. [2, -5, 1], you can use the standard read parser:
Prelude> scriePolinom (read "[2, -5, 1]")
"[2,-5,1]"
Or if, as Daniel Sanchez assumes, you expect just a sequence of space-separated numbers in decimal notation, you can first split up these numbers as words, then read each one individually:
Prelude> scriePolinom . map read $ words "2 -5 1"
"[2,-5,1]"
To use this in an executable program, you can use the ready-build combination of getLine and read:
main :: IO ()
main = do
a <- readLn
putStrLn $ scriePolinom a
Note that read/readLn are not robust with respect to malformed input (they're not total functions) – this will just crash the program unless you wrap it in explicit exception handling. For serious applications I recommend using a full-featured parsing library, such as megaparsec.
Haskell, 37 bytes
f l=[b|(a,b)<-zip[x<'b'|x<-'a':l]l,a]
Try it online!
I'm trying to get a number from IO like this:
numberString <- getLine
print 3 + read numberString
This works if numberString is a good string of number (like "3241"), but when it's not something that good (like "124gjh"), it throws an exception:
*** Exception: Prelude.read: no parse
There's a reads function which returns a [(a0, String)] and when nothing is matched this would be a []. Is there an easy way that I have something like this:
read' :: String -> Maybe a
so that I just get a Nothing if things doesn't work instead of just stopping abruptly?
There is readMaybe right in Text.Read which should do exactly what you asked for:
Prelude> import Text.Read(readMaybe)
Prelude Text.Read> readMaybe "3241" :: Maybe Int
Just 3241
Prelude Text.Read> readMaybe "Hello" :: Maybe Int
Nothing
from haskell examples http://learnyouahaskell.com/types-and-typeclasses
ghci> read "5" :: Int
5
ghci> read "5" :: Float
5.0
ghci> (read "5" :: Float) * 4
20.0
ghci> read "[1,2,3,4]" :: [Int]
[1,2,3,4]
ghci> read "(3, 'a')" :: (Int, Char)
(3, 'a')
but when I try
read "asdf" :: String
or
read "asdf" :: [Char]
I get exception
Prelude.read No Parse
What am I doing wrong here?
This is because the string representation you have is not the string representation of a String, it needs quotes embedded in the string itself:
> read "\"asdf\"" :: String
"asdf"
This is so that read . show === id for String:
> show "asdf"
"\"asdf\""
> read $ show "asdf" :: String
"asdf"
As a side note, it's always a good idea to instead use the readMaybe function from Text.Read:
> :t readMaybe
readMaybe :: Read a => String -> Maybe a
> readMaybe "asdf" :: Maybe String
Nothing
> readMaybe "\"asdf\"" :: Maybe String
Just "asdf"
This avoids the (in my opinion) broken read function which raises an exception on parse failure.
The problem is that I need to input a decimal number, like a float, with right format.
However, I don't know how can I parse the input to ensure it's really a float. If not, I need to putStrLn "ERR". Assume I have the consecutive input.
As example shown below, what condition can I add after IF to exclude the wrong input format, like 1.2.e!##$, which I should give an "ERR" and loop main rather than get an error and exit program immediately.
input <- getLine
if (read input1 :: Float) > 1.0
then do
let result1 = upperbound (read input :: Float)
let result2 = lowerbound (read input :: Float)
print result4
print result3
main
else do
putStrLn"ERR"
main
read is a partial function - it works only on a subset of the input domain. A better example for a partial function is head: it works well on non-empty lists, but will throw an error on an empty list - and you can only handle errors when in the IO monad. Partial functions are useful in some cases, but you should generally avoid using them. So like head, read is an unsafe function - it may fail when the input cannot be parsed.
read has a safe alternative: readMaybe from Text.Read.
readMaybe :: Read a => String -> Maybe a
readMaybe will never fail - if it can't parse a string, it will return Nothing. Handling a Maybe value is a simple task and can be done in several ways (case expressions, Data.Maybe functions, do notation and so on). Here's an example using a case expression:
import Text.Read
...
case (readMaybe input :: Maybe Float) of
Just f | f > 1.0 -> ...
| otherwise -> ...
Nothing -> ...
This article can be helpful in understanding the different ways of error handling in Haskell.
Prelude> let s1 = "1.223"
Prelude> let s2 = "1"
Prelude> let s3 = "1.2.e!##$"
Prelude> read s1 :: Float
1.223
Prelude> read s2 :: Float
1.0
Prelude> read s3 :: Float
*** Exception: Prelude.read: no parse
read throws an exception when it can't parse the string. You need to handle that exception.