mfix不能按预期工作 [英] `mfix` not working as expected

查看:131
本文介绍了mfix不能按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望以下代码首先提示 start:,然后等待用户响应,然后再回送先前的用户响应,然后等待新的用户响应:

I expected the following code to first prompt start:, then wait for a user response, before echoing the previous user response back, and awaiting a new one:

import System.IO (hFlush, stdout)
import Control.Monad.Fix (mfix)

f :: [String] -> IO [String]
f = mapM $ \x -> putStr x >> putStr ": " >> hFlush stdout >> getLine

g x = f ("start":x)

main = mfix g

但是,在输入第一行后,它会在中无限期阻止线程。

But it gives the error thread blocked indefinitely in an MVar operation after the first line is entered.

为什么会这样,我该如何解决它(原谅双关语)?

Why is this and how can I fix it (excuse the pun)?

推荐答案

不能工作的是在 mfix f 中只有一次在 f 中运行任何效果。这来自收紧规则

The reason why this can't work is that in mfix f runs any effect in f exactly once. This follows from the tightening rule

mfix (\x -> a >>= \y -> f x y)  =  a >>= \y -> mfix (\x -> f x y)

特别是

in particular

mfix (\x -> a >> f x)  =  a >> mfix f

。因此,固定点仅针对一元操作内的纯粹(懒惰计算)值进行计算,而对于效果而言则不是 。在你的情况下,使用 mfix 要求打印/读取字符一次,以使输入等于输出,这是不可能的。对于 mfix ,这不是合适的用例。例如,您可以使用 mfix IO 来构造 IO 就像这些例子

for any correct instance of MonadFix. So the fixed point is only computed for the pure (lazily computed) value inside the monadic action, not for the effects. In your case using mfix asks for printing/reading characters just once in such a way that the input is equal to the output, which is impossible. This isn't a proper use case for mfix. You'd use mfix with IO for example to construct a cyclic data structure in IO like in these examples.

在你的情况下,你应该使用 iterateM _ 或类似的东西,而不是 mfix 。另请参阅 iterate + forever = iterateM?重复反馈的行动

In your case you should use iterateM_ or something similar rather than mfix. see also iterate + forever = iterateM? Repeating an action with feedback.

这篇关于mfix不能按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆