该System.IO文档包含一个神秘的,未公开的函数fixIO.它的来源只会增加神秘感:
fixIO :: (a -> IO a) -> IO a
fixIO k = do
m <- newEmptyMVar
ans <- unsafeInterleaveIO (takeMVar m)
result <- k ans
putMVar m result
return result
Run Code Online (Sandbox Code Playgroud)
这似乎与取消引用NULL(从空的MVar读取)相当.确实,尝试一下:
import System.IO
main = fixIO $ \x -> putStrLn x >> return x
Run Code Online (Sandbox Code Playgroud)
导致错误"线程在MVar操作中无限期地被阻塞"
除了Simon Peyton-Jones本人提供的15年前的消息之外,搜索没有任何结果,他提供了上述来源,并希望它能使意义明确(而且我在这里).
有人可以对此有所了解吗?fixIO做什么以及何时应该使用它?
ram*_*ion 12
fixIO是IO的等效fix.
您可能已经看到了斐波那契序列的这个定义:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
它重用了fibs定义中的变量fibs来进行核心化.它的工作原理是因为我们利用懒惰来定义fibs需要使用之前的每个元素.
我们可以使用fix它来做同样的事情,而不必定义一个变量,为我们打结:
fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
如果你不特别需要保留整个斐波那契序列,这是很方便的,你只想知道它的第十个元素:
? (fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) !! 9
55
Run Code Online (Sandbox Code Playgroud)
fixIO类似,但它允许你递归IO动作的输出.这就是为什么你得到了"线程阻塞"错误 - 你在没有定义它的情况下使用了corecursive结果.
? fmap (take 10) . fixIO $ \fibs -> putStrLn "computing fibs" >> return (1 : 1 : zipWith (+) fibs (tail fibs))
computing fibs
[1,1,2,3,5,8,13,21,34,55]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1052 次 |
| 最近记录: |