我对haskell几乎一无所知,我正在阅读大量的教程和代码示例,以了解 Haskell 的IO,但我仍然不清楚。
所有例子都是:
main = do
putStrLn "Hello, what's your name?"
name <- getLine
putStrLn ("Hey " ++ name ++ ", welcome !")
他们从IO读取一个字符串,还有很多其他的例子可以对我不理解的输入进行一些自定义。
我的问题很简单:如何阅读Int
,Float
,Double
或Char
,例如在 C 中使用scanf
用格式字符串?
任何人都可以帮我解释IO定制或技巧吗?
提示:如果代码附带了一个主函数 太棒了 - 它会让测试变得更容易。
我在C
,C++
,Java
,C#
,Matlab
和PHP
方面拥有非常好的编码经验。
答案 0 :(得分:4)
最直接的方法是使用read
(您通常必须提供显式类型),如
main = do
putStrLn "Hello, what's your age?"
age <- liftM read getLine :: IO Int
putStrLn ("Hey " ++ (show age) ++ ", welcome !")
如果您知道字符串只包含单个值(如果它无法将字符串解析为所需的数据类型,则抛出异常),这很有效。对于更复杂的解析,我通常会直接跳转到Parsec解析器组合库(这可能是Haskell中您需要的所有解析器,但也可以以最小的开销处理简单的作业)。如果这不适合您,快速搜索Hackage会显示一些候选库提供更简单的类似scanf的功能:请参阅Text.XFormat.Read和Text.PrintScan,尽管我不能亲自担保。
答案 1 :(得分:3)
isturdy的回答是有效的,但是如果你想要更简单的东西,最简单的方法是逐步完成:
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
getLine
的类型为IO String
- 它将输入读作String
。然后,您可以使用read
更改此字符串的类型(并指明您想要的类型)。对于类似scanf
的体验,你可以尝试这样的事情:
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 ""
答案 2 :(得分:1)
你应该深入阅读类型类。它是可以从字符串读取的值的标准类型,在不需要错误报告时在受控环境中非常有用。如果您希望读取自己的数据类型,则可能必须使用deriving Read
语句。
但是,如果想要读取任意输入,则使用parsec库是标准的。 Parsec是具有多个预定义基本解析器的解析器组合器库。 extra package为数字提供了许多解析器。还存在特殊的高速解析器组合库和解析器生成器。