这是我之前提到的question的后续行动。我想知道,在IORef
的每次通话中,接受的解决方案中下面O(1)
中的路径列表是否更新fetch
。我怀疑是因为IORef
可能只是保持指向列表头部的指针(而不是遍历和复制整个列表,每次都是O(n)。只需将指针更改为新头应为O( 1),并应防止对整个列表进行急切评估)。但是,ghc-core
不会显示低级代码。所以,问这里:
mklstream :: L.ByteString -> (IO S.ByteString -> IO r) -> IO r
mklstream lbs sink = do
ref <- newIORef (L.toChunks lbs)
let fetch :: IO S.ByteString
fetch = do chunks <- readIORef ref
case chunks of
[] -> return S.empty
(c:cs) -> do writeIORef ref cs
return c
sink fetch
答案 0 :(得分:7)
是的,在GHC中它是O(1)。从IORef
读取和写入的内容与实现中的其他所有内容都用作数据表示的指针完全相同。实际上,您只能从writeIORef
的类型中知道它对数据没有什么特别之处:
writeIORef :: IORef a -> a -> IO ()
由于a
完全不受约束,writeIORef
无法检查数据,特别是无法遍历您提交的任何列表。 (这不太令人信服 - 即使使用无约束类型,运行时也可以执行它喜欢的任何操作,并且您可能认为writeIORef
是运行时原语 - 但无论如何在这种情况下都证明它是真的。)< / p>