Loops Haskell执行IO循环的方法(没有显式递归)?
我想从STDIN中读取一个由换行符分隔的字符串列表,直到看到一个新行,我想执行Loops Haskell执行IO循环的方法(没有显式递归)?,loops,haskell,recursion,monads,Loops,Haskell,Recursion,Monads,我想从STDIN中读取一个由换行符分隔的字符串列表,直到看到一个新行,我想执行IO[String]类型的操作。下面是使用递归的方法: myReadList :: IO String myReadList = go [] where go :: [String] -> IO [String] go l = do { inp <- getLine; if (inp == "") then
IO[String]
类型的操作。下面是使用递归的方法:
myReadList :: IO String
myReadList = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}
myReadList::IO字符串
myReadList=go[]
哪里
go::[String]->IO[String]
去做{
inp(a->Bool)->[ma]->m[a]
whileM p[]=返回[]
whileM p(x:xs)=do
s与您的whileM
相同,只是它将一个动作(而不是列表)作为第二个参数
myReadList = unfoldWhileM (/= "") getLine
是的,对于抽象出前面答案中提到的显式递归,有一个库非常有用。对于感兴趣的人来说
然而,还有另一种方法。之前,我努力做这份工作,知道哈斯克尔默认是懒惰的,我第一次尝试
(sequence . repeat $ getLine) >>= return . takeWhile (/="q")
我希望上面的代码可以将输入的行收集到一个IO[String]
类型中。不……它可以无限期运行,而且IO活动看起来一点也不懒惰。在这一点上可能也很方便。它是一个只有2个函数的简单库
run :: T a -> IO a
interleave :: IO a -> T a
因此,run
执行一个惰性IO操作并将其转换为IO操作,interleave
执行相反的操作
import qualified System.IO.Lazy as LIO
gls = LIO.run (sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/="q")
Prelude> gls >>= return . sum . fmap (read :: String -> Int)
1
2
3
4
q
10
使用包的有效流的解决方案:
导入流媒体
导入符合条件的流媒体。前奏为S
main::IO()
main=do
result whileM在控制中。Monad.Loops.@n.m.我知道,但它做了一些其他的事情。它还有一个不同的签名:Monad m=>m Bool->m a->m[a]
你的版本似乎很接近unbowwhilem,除了你做了一个你并不真正需要的单子动作列表(你用repeat生成列表).ReadingControl.Monad.Loops
证实了人们可以定义的循环形式太多了。我在搜索类似于doWhile::(a->IO Bool)->IO a->IO[a]
,我想我以前用过,但没有找到类似的东西。只有Unfollorm
和friends看起来那么通用,但没有将保护与循环体分开。我还想知道使用循环库是否会使代码更难阅读,因为大多数程序员都没有记住100个循环变体(即使他们可能猜到了意图)。
import qualified System.IO.Lazy as LIO
gls = LIO.run (sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/="q")
Prelude> gls >>= return . sum . fmap (read :: String -> Int)
1
2
3
4
q
10
import Streaming
import qualified Streaming.Prelude as S
main :: IO ()
main = do
result <- S.toList_ . S.takeWhile (/="") . S.repeatM $ getLine
print result
main :: IO ()
main = do
result <- S.toList_
$ S.zipWith (\_ s -> s)
(S.repeatM $ putStrLn "Write something: ")
(S.takeWhile (/="") . S.repeatM $ getLine)
print result