hug*_*omg 7 haskell control-flow
stdout :: () -> Consumer String IO r
stdout () = forever $ do
str <- request ()
lift $ putStrLn str
stdin :: () -> Producer String IO ()
stdin () = loop
where
loop = do
eof <- lift $ IO.hIsEOF IO.stdin
unless eof $ do
str <- lift getLine
respond str
loop
Run Code Online (Sandbox Code Playgroud)
正如教程本身所述,由于需要检查输入的结束,P.stdin有点复杂.
有没有什么好方法可以重写P.stdin,不需要手动尾递归循环,并使用像P.stdout那样的高阶控制流组合器?在命令式语言中,我将使用结构化的while循环或break语句来执行相同的操作:
while(not IO.isEOF(IO.stdin) ){
str <- getLine()
respond(str)
}
forever(){
if(IO.isEOF(IO.stdin) ){ break }
str <- getLine()
respond(str)
}
Run Code Online (Sandbox Code Playgroud)
Gab*_*lez 11
我更喜欢以下内容:
import Control.Monad
import Control.Monad.Trans.Either
loop :: (Monad m) => EitherT e m a -> m e
loop = liftM (either id id) . runEitherT . forever
-- I'd prefer 'break', but that's in the Prelude
quit :: (Monad m) => e -> EitherT e m r
quit = left
Run Code Online (Sandbox Code Playgroud)
你这样使用它:
import Pipes
import qualified System.IO as IO
stdin :: () -> Producer String IO ()
stdin () = loop $ do
eof <- lift $ lift $ IO.hIsEOF IO.stdin
if eof
then quit ()
else do
str <- lift $ lift getLine
lift $ respond str
Run Code Online (Sandbox Code Playgroud)
请参阅此博客文章,我将解释此技术.
我不在教程中使用它的唯一原因是我认为它不太适合初学者.
看起来像是一份工作whileM_:
stdin () = whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) (lift getLine >>= respond)
Run Code Online (Sandbox Code Playgroud)
或者,使用与原始示例类似的do-notation:
stdin () =
whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) $ do
str <- lift getLine
respond str
Run Code Online (Sandbox Code Playgroud)
该monad-loops软件包还提供了whileM返回中间结果列表而不是忽略重复操作的结果以及其他有用的组合器.
| 归档时间: |
|
| 查看次数: |
5448 次 |
| 最近记录: |