Reputation: 2333
I know almost nothing about haskell and I'm reading lots of tutorials and code samples to understand Haskell's IO, but it is still not clear to me.
All examples are like:
main = do
putStrLn "Hello, what's your name?"
name <- getLine
putStrLn ("Hey " ++ name ++ ", welcome !")
They read a string from IO and there are many other examples that do some customization on input that I don't understand.
My question is simply: How to read Int
, Float
, Double
or Char
like using scanf
in C with a format string?
And can anyone help me with a clear explanation to IO customization or tricks?
Hint: if the code comes with a main function that would be great - it would make testing easier.
I have very good coding experience in C
, C++
, Java
, C#
, Matlab
and PHP
.
Upvotes: 2
Views: 1402
Reputation: 22173
isturdy's answer is valid, but in case you want something a bit simpler, the easiest approach is to do it step-by-step:
main = do
i' <- getLine -- some integral input; it will be received as a String
d' <- getLine -- some floating input; also will be received as a String
let i = read i' :: Int -- i is an Int now
d = read d' :: Double -- d is a Double now
putStr "" -- so that GHC doesn't complain
The type of getLine
is IO String
- it reads input as a String
. You can then change the type of this string with read
(and indicating what type you want). As for a scanf
-like experience, you can try something like this:
main = do
inp <- getLine -- the input is an Int, a String and a Double, like: 4 derp 2.7
let list = words inp -- divide the input String into a list of Strings
val = read (list !! 0) :: Int -- val equals 4, its type is Int
str = list !! 1 -- str is a String ("derp"), no additional action required
dbl = read (list !! 2) :: Double -- dbl equals 2.7 and is a Double
putStr ""
Upvotes: 3
Reputation: 622
You should dig into Read typeclass. It is a standard typecalss for values that can be read from string and very useful in controlled environment when there is no need for error reporting. If you wish to read your own datatype, you probably have to use deriving Read
statement.
However, if one want to read arbitrary input, it is standard to use parsec library. Parsec is parser combinator library with several predefined basic parsers. An extra package provides many parsers for numbers. Special hi-speed parser combinator libraries and parser generator also exist.
Upvotes: 1
Reputation: 1231
The most direct way is to use read
(you will often have to provide an explicit type), as in
main = do
putStrLn "Hello, what's your age?"
age <- liftM read getLine :: IO Int
putStrLn ("Hey " ++ (show age) ++ ", welcome !")
This works well if you know that the string contains just the single value (it throws an exception if it cannot parse the string as the desired datatype). For more complex parsing, I usually jump straight to the Parsec parser combinator library (which is probably all the parser you will ever need in Haskell, but also handles simple jobs with minimal overhead). If that does not suit you a quick search of Hackage reveals some candidate libraries offering a simpler scanf-like function: see, among others, Text.XFormat.Read and Text.PrintScan, although I cannot personally vouch for either.
Upvotes: 4