Haskell 如何将System.IO.Unsafe与TVars一起使用?

Haskell 如何将System.IO.Unsafe与TVars一起使用?,haskell,Haskell,我想在STM事务中调用UDP send函数,这样我就可以避免下面这样的代码,在最终发送值之前读取m′(并且可以由其他线程更新),两个连续的where子句使我看起来非常“无助” sendRecv s newmsgs q m=do 无法从STM块内部执行m'IO,因为无法撤消常规IO。如果要执行某些IO,必须在STM块中安排,但在外部执行。例如: foo tvar = do scheduledAction <- atomically $ do v <- readT

我想在STM事务中调用UDP send函数,这样我就可以避免下面这样的代码,在最终发送值之前读取m′(并且可以由其他线程更新),两个连续的where子句使我看起来非常“无助”

sendRecv s newmsgs q m=do

无法从STM块内部执行m'IO,因为无法撤消常规IO。如果要执行某些IO,必须在STM块中安排,但在外部执行。例如:

foo tvar = do
    scheduledAction <- atomically $ do
        v <- readTVar tvar
        when v retry
        return (sendSomethingOnASocket "okay, we're done here")
    scheduledAction
foo-tvar=do
scheduledAction如果您确实需要在事务中执行IO,那么您应该确保首先阅读文档,因为有几个问题需要注意。特别是,如果必须重试事务,IO操作可能会运行多次


也就是说,我认为这在这种情况下不合适,您可能应该重构代码,以便将消息发送到事务之外。

是否有可能将线程a的事务优先于线程b?例如,如果线程a不断地进行事务,而线程b更不频繁地进行事务,那么b是否会“中断”a?我尝试了一个MVar,其中b可以阻止a运行一段时间。但并不优雅。@JFritsch MVAR和STM并没有真正的混合。我不知道如何要求一个线程优先于另一个线程。但是,如果您不是livelocking,两个线程最终都应该取得进展。失败的事务会再次透明地重试,而我不会在代码中处理它吗?@JFritsch我只需要一些随机STM代码来充实示例。不过,要回答您的直接问题:是的,失败的事务将透明地再次重试;但是失败的一种方法是显式失败(通过调用
重试
)。例如,在银行系统中,当您注意到他们想要支取的金额超过账户余额时,您可能会在支取交易中显式地调用
retry
。这太棒了!再次感谢。还感谢@hammar,他最近向我解释了什么是行动。
foo tvar = do
    scheduledAction <- atomically $ do
        v <- readTVar tvar
        when v retry
        return (sendSomethingOnASocket "okay, we're done here")
    scheduledAction