gpt4 book ai didi

haskell - 包含在 IO 中的惰性列表

转载 作者:行者123 更新时间:2023-12-01 07:36:35 25 4
gpt4 key购买 nike

假设代码

f :: IO [Int]
f = f >>= return . (0 :)

g :: IO [Int]
g = f >>= return . take 3

当我运行 g在 ghci 中,它会导致 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 中,尝试也是懒惰地构建列表。单子(monad)。以便有人阅读 h 的结果甚至可以在列表完成之前开始使用它(因为它甚至可能是无限的)。如果阅读结果的人只关心第一个 3无论如何,列表的其余部分甚至不必构造。而且我感觉这是不可能的:/。

最佳答案

是的,IO是罪魁祸首。 >>=对于 IO在“世界状态”中是严格的。如果你写 m >>= h ,您将获得一个首先执行操作 m 的操作,然后应用 h到结果,最后执行 Action h产量。你的 f 没关系action 不会“做任何事情”;无论如何都必须执行。因此,您最终会陷入无限循环,开始 f一遍又一遍的 Action 。

谢天谢地,有办法解决这个问题,因为 IOMonadFix 的一个实例.您可以“神奇地”访问 IO 的结果。 Action 中的 Action 。至关重要的是,该访问必须足够懒惰,否则您将陷入无限循环。

import Control.Monad.Fix
import Data.Functor ((<$>))

f :: IO [Int]
f = mfix (\xs -> return (0 : xs))

-- This `g` is just like yours, but prettier IMO
g :: IO [Int]
g = take 3 <$> f

GHC 中甚至还有一些语法糖可以让你使用 do rec 的符号关键字或 mdo符号。
{-# LANGUAGE RecursiveDo #-}

f' :: IO [Int]
f' = do
rec res <- (0:) <$> (return res :: IO [Int])
return res

f'' :: IO [Int]
f'' = mdo
res <- f'
return (0 : res)

更多有趣的使用方法示例 MonadFix ,见 Haskell Wiki .

关于haskell - 包含在 IO 中的惰性列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32489732/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com