Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops Haskell执行IO循环的方法(没有显式递归)?_Loops_Haskell_Recursion_Monads - Fatal编程技术网

Loops Haskell执行IO循环的方法(没有显式递归)?

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

我想从STDIN中读取一个由换行符分隔的字符串列表,直到看到一个新行,我想执行
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生成列表).Reading
Control.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