假设这段代码:
当我在ghci中运行
f :: IO [Int]
f = f >>= return . (0 :)
g :: IO [Int]
g = f >>= return . take 3
当我在ghci中运行
g
时,它会导致stackoverflow。但是我想也许它可以被惰性地评估并生成包含[0, 0, 0]
的IO
。我怀疑是IO
的问题,但我真的不知道。显然以下代码可以工作:f' :: [Int]
f' = 0 : f'
g' :: [Int]
g' = take 3 f'
编辑:实际上我对于这样一个简单的函数 f
不感兴趣,原始代码看起来更像是这样:
h :: a -> IO [Either b c]
h a = do
(r, a') <- h' a
case r of
x@(Left _) -> h a' >>= return . (x :)
y@(Right _) -> return [y]
h' :: IO (Either b c, a)
-- something non trivial
main :: IO ()
main = mapM_ print . take 3 =<< h a
h
执行一些IO
计算,并将无效(Left
)响应存储在列表中,直到产生有效响应(Right
)。尝试懒惰地构建列表,即使我们在IO
单子中也是如此。因此,读取h
的结果的人甚至可以在完成之前开始消耗列表(因为它甚至可能是无限的)。如果读取结果的人只关心前三个条目,那么甚至不需要构造列表的其余部分。我感觉这似乎是不可能的 :/。
h'
会调用h
吗?你能展示一下真正的代码吗?你希望它只执行足够产生需求结果的IO
,还是无论如何都要全部执行? - dfeuerh
不是从h'
中调用的。 - jakubdanielunsafeInterleaveIO
是你唯一的选择。 - dfeuer