本文介绍了la版本的mapM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 假设,我在处理IO时收到大量项目列表: 不要使用 如果您想用 getLargeList 的输出替换 prompt100 >,您只需写: yourProducer :: Producer b IO() yourProducer = do xs < - lift getLargeList mapM_ yield xs ...然后执行: p> >>> runPipe $ printer< +<采取'1 +< yourProducer 这将懒散地列出列表,并且永远不会在内存中构建列表,而且不会使用不安全的 IO hacks。要更改您需要的元素数量,只需将您传递的值更改为 take' ,阅读 管道教程在 Control.Pipe.Tutorial 。 要详细了解为什么惰性IO导致问题,请阅读Oleg关于主题的原始幻灯片,您可以在其中找到此处。他擅长解释使用惰性IO的问题。任何时候你感觉不得不使用惰性IO,你真正想要的是一个迭代库。 Suppose, I'm getting large list of items while working with IO:as <- getLargeListNow, I'm trying to apply fn :: a -> IO b onto as:as <- getLargeListbs <- mapM fn asmapM has type mapM :: Monad m => (a -> m b) -> [a] -> m [b], and that's what I need in terms of type matching. But it builds all the chain in memory until return the result. I'm looking for analog of mapM, which will work lazily, so that I may use head of bs while tail is still building. 解决方案 Do not use unsafeInterleaveIO or any lazy IO for that matter. This is precisely the problem that iteratees were created to address: avoiding lazy IO, which gives unpredictable resource management. The trick is to never build the list and constantly stream it using iteratees until you are done using it. I will use examples from my own library, pipes, to demonstrate this.First, define:import Control.Monadimport Control.Monad.Transimport Control.Pipe-- Demand only 'n' elementstake' :: (Monad m) => Int -> Pipe a a m ()take' n = replicateM_ n $ do a <- await yield a-- Print all incoming elementsprinter :: (Show a) => Consumer a IO rprinter = forever $ do a <- await lift $ print aNow let's be mean to our user and demand they produce the really large list for us:prompt100 :: Producer Int IO ()prompt100 = replicateM_ 1000 $ do lift $ putStrLn "Enter an integer: " n <- lift readLn yield nNow, let's run it:>>> runPipe $ printer <+< take' 1 <+< prompt100Enter an integer:3<Enter>3It only prompts the user for one integer, since we only demand one integer!If you want to replace prompt100 with output from getLargeList, you just write:yourProducer :: Producer b IO ()yourProducer = do xs <- lift getLargeList mapM_ yield xs... and then run:>>> runPipe $ printer <+< take' 1 <+< yourProducerThis will lazily stream the list and never build the list in memory, all without using unsafe IO hacks. To change how many elements you demand, just change the value you pass to take'For more examples like this, read the pipes tutorial at Control.Pipe.Tutorial.To learn more about why lazy IO causes problems, read Oleg's original slides on the subject, which you can find here. He does a great job of explaining the problems with using lazy IO. Any time you feel compelled to use lazy IO, what you really want is an iteratee library. 这篇关于la版本的mapM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
11-01 20:07