Haskell:优雅地循环用户输入
Haskell: looping over user input gracefully
这是来自 Learn You a Haskell
的示例:
main = do
putStrLn "hello, what's your name?"
name <- getLine
putStrLn ("Hey, " ++ name ++ ", you rock!")
为清楚起见,没有 do
的相同重做:
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
putStrLn $ "Hey, " ++ name ++ ", you rock!"
我应该如何干净地循环它(直到 "q"),Haskell 方式(不鼓励使用 do
)?
我从Haskell - loop over user input
那里借来的
main = mapM_ process . takeWhile (/= "q") . lines =<< getLine
where process line = do
putStrLn line
初学者,但不会循环。
您可以再次调用 main 并检查您的字符串是否为 "q"。
import Control.Monad
main :: IO ()
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
when (name /= "q") $ (putStrLn $ "Hey, " ++ name ++ ", you rock!") >> main
λ> main
hello, what's your name?
Mukesh Tiwari
Hey, Mukesh Tiwari, you rock!
hello, what's your name?
Alexey Orlov
Hey, Alexey Orlov, you rock!
hello, what's your name?
q
λ>
也许你也可以通过调整 System.IO.Lazy
包来在 IO 类型上使用惰性。它基本上只包含 run :: T a -> IO a
和 interleave :: IO a -> T a
函数来回将 IO 动作转换为惰性动作。
import qualified System.IO.Lazy as LIO
getLineUntil :: String -> IO [String]
getLineUntil s = LIO.run ((sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/=s))
printData :: IO [String] -> IO ()
printData d = d >>= print . sum . map (read :: String -> Int)
*Main> printData $ getLineUntil "q"
1
2
3
4
5
6
7
8
9
q
45
在上面的代码中,我们通过 repeat $ LIO.interleave getLine
类型 [T String]
构造了一个惰性 getLine
的无限列表,并通过 sequence
将其转换为 T [String]
输入并继续阅读,直到收到 "q"。 printData
效用函数正在汇总并打印输入的整数。
这是来自 Learn You a Haskell
的示例:
main = do
putStrLn "hello, what's your name?"
name <- getLine
putStrLn ("Hey, " ++ name ++ ", you rock!")
为清楚起见,没有 do
的相同重做:
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
putStrLn $ "Hey, " ++ name ++ ", you rock!"
我应该如何干净地循环它(直到 "q"),Haskell 方式(不鼓励使用 do
)?
我从Haskell - loop over user input
那里借来的main = mapM_ process . takeWhile (/= "q") . lines =<< getLine
where process line = do
putStrLn line
初学者,但不会循环。
您可以再次调用 main 并检查您的字符串是否为 "q"。
import Control.Monad
main :: IO ()
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
when (name /= "q") $ (putStrLn $ "Hey, " ++ name ++ ", you rock!") >> main
λ> main
hello, what's your name?
Mukesh Tiwari
Hey, Mukesh Tiwari, you rock!
hello, what's your name?
Alexey Orlov
Hey, Alexey Orlov, you rock!
hello, what's your name?
q
λ>
也许你也可以通过调整 System.IO.Lazy
包来在 IO 类型上使用惰性。它基本上只包含 run :: T a -> IO a
和 interleave :: IO a -> T a
函数来回将 IO 动作转换为惰性动作。
import qualified System.IO.Lazy as LIO
getLineUntil :: String -> IO [String]
getLineUntil s = LIO.run ((sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/=s))
printData :: IO [String] -> IO ()
printData d = d >>= print . sum . map (read :: String -> Int)
*Main> printData $ getLineUntil "q"
1
2
3
4
5
6
7
8
9
q
45
在上面的代码中,我们通过 repeat $ LIO.interleave getLine
类型 [T String]
构造了一个惰性 getLine
的无限列表,并通过 sequence
将其转换为 T [String]
输入并继续阅读,直到收到 "q"。 printData
效用函数正在汇总并打印输入的整数。