做IO循环的Haskell方法(无需显式递归)? [英] The Haskell way to do IO Loops (without explicit recursion)?

查看:112
本文介绍了做IO循环的Haskell方法(无需显式递归)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从STDIN读取由换行符分隔的字符串列表,直到见证新行并且我想要类型为IO [String]的操作.这是我如何使用递归的方法:

I want to read a list of strings seperated by newlines from STDIN, until a new line is witnessed and I want an action of the type IO [String]. Here is how I would do it with recursion:

myReadList :: IO String
myReadList = go []
where 
    go :: [String] -> IO [String]   
    go l = do {
                 inp <- getLine;
                 if (inp == "") then 
                     return l;
                 else go (inp:l);
                }

但是,这种使用go的方法会掩盖可读性,并且这种模式非常普遍,以至于人们理想地希望将其抽象出来.

However, this method of using go obscures readability and is a pattern so common that one would ideally want to abstract this out.

所以,这是我的尝试:

whileM :: (Monad m) => (a -> Bool) -> [m a] -> m [a]
whileM p []     = return []
whileM p (x:xs) = do
    s <- x
    if p s
    then do
        l <- whileM p xs
        return (s:l)
    else
        return []

myReadList :: IO [String]
myReadList = whileM (/= "") (repeat getLine)

我猜想此whileM已有一些默认实现或类似的东西.但是我找不到它.

I am guessing there is some default implementation of this whileM or something similar already. However I cannot find it.

有人可以指出解决这个问题的最自然,最优雅的方法是什么吗?

Could someone point out what is the most natural and elegant way to deal with this problem?

推荐答案

unfoldWhileM is same as your whileM except that it takes an action (not a list) as second argument.

myReadList = unfoldWhileM (/= "") getLine

这篇关于做IO循环的Haskell方法(无需显式递归)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆