Haskell、通道、STM、线程、消息传递

2024-02-12

我正在尝试使用 Channels/STM 在 Haskell 中实现消息传递。也许这是一个糟糕的想法,并且有更好的方法在 Haskell 中实现/使用消息传递。如果是这种情况,请告诉我;然而,我的探索提出了一些关于并发 Haskell 的基本问题。

我听说过有关 STM 的伟大事情,特别是在 Haskell 中的实现。由于它支持读取和写入,并且具有一些安全优势,因此我认为应该从这里开始。这提出了我最大的问题:

msg <- atomically $ readTChan chan

其中 chan 是 TChan Int,导致等待通道上有值吗?

考虑以下程序:

p chan = do
    atomically $ writeTChan chan 1
    atomically $ writeTChan chan 2

q chan = do
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan
    -- for testing purposes
    putStrLn $ show msg1 
    putStrLn $ show msg2

main = do
    chan <- atomically $ newTChan
    p chan
    q chan

使用 ghc --make -threaded 编译它,然后运行该程序,实际上您会得到 1 后跟 2 打印到控制台。现在,假设我们这样做

main = do 
    chan <- atomically $ newTChan
    forkIO $ p chan 
    forkIO $ q chan

反而。现在,如果我们使用 -threaded,它要么什么也不打印,要么打印 1,要么打印 1 后跟 2 到终端;但是,如果不使用 -threaded 进行编译,它总是打印 1 后跟 2。 问题 2:-threaded 和非 -threaded 之间有什么区别?我想它们并不是真正作为并发事物运行,它们只是一个接一个地运行。这与下面的内容是一致的。

现在,在我的想法中,如果我让 p 和 q 同时运行;也就是说,我对它们进行了分叉,它们应该能够以相反的顺序运行。假如

main = do
    chan <- atomically newTChan
    forkIO $ q chan
    forkIO $ p chan

现在,如果我在没有 -threaded 的情况下编译它,我永远不会在控制台上打印任何内容。如果我使用 -threaded 进行编译,有时会这样做。尽管如此,获得 1 后又获得 2 的情况非常罕见——通常只有 1 或什么都没有。我也用 Control.Concurrent.Chan 尝试过这一点,并得到了一致的结果。

第二个大问题:通道和分叉如何一起发挥作用,上面的程序中发生了什么?

无论如何,看来我不能这么天真地用STM来模拟消息传递。也许 Cloud Haskell 是解决这些问题的一个选择——我真的不知道。任何有关如何在序列化~~>写入套接字~~>从套接字读取~~>反序列化的情况下传递消息的任何信息都将受到极大的赞赏。


不,你的想法是对的——这就是什么TChans 代表 - 你只是错过了一个小点forkIO:

问题是你的主线程不会等待用创建的线程终止forkIO (请参阅此处以供参考 https://hackage.haskell.org/package/base-4.8.0.0/docs/Control-Concurrent.html#g:12)

所以如果我使用hint参考文献中给出:

import Control.Concurrent
import Control.Concurrent.STM

p :: Num a => TChan a -> IO ()
p chan = do
    atomically $ writeTChan chan 1
    atomically $ writeTChan chan 2

q chan = do
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan
    -- for testing purposes
    putStrLn $ show msg1 
    putStrLn $ show msg2

main :: IO ()
main = do
    children <- newMVar []
    chan <- atomically $ newTChan
    _ <- forkChild children $ p chan
    _ <- forkChild children $ q chan
    waitForChildren children
    return ()

waitForChildren :: MVar [MVar ()] -> IO ()
waitForChildren children = do
  cs <- takeMVar children
  case cs of
    []   -> return ()
    m:ms -> do
      putMVar children ms
      takeMVar m
      waitForChildren children

forkChild :: MVar [MVar ()] -> IO () -> IO ThreadId
forkChild children io = do
  mvar <- newEmptyMVar
  childs <- takeMVar children
  putMVar children (mvar:childs)
  forkFinally io (\_ -> putMVar mvar ())

它按预期工作:

d:/Temp $ ghc --make -threaded tchan.hs
[1 of 1] Compiling Main             ( tchan.hs, tchan.o )
Linking tchan.exe ...
d:/Temp $ ./tchan.exe 
1
2
d:/Temp $

当然,如果您将呼叫切换到,它会继续工作p and q too

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell、通道、STM、线程、消息传递 的相关文章

  • 镜头中的观看和使用有什么区别?

    有什么区别 view MonadReader s m gt Getting a s a gt m a and use MonadState s m gt Getting a s a gt m a in 控制镜头吸气剂 https hacka
  • 在 Haskell 中,如何将嵌套上下文中的函数“应用”到上下文中的值?

    nestedApply Applicative f Applicative g gt g f a gt b gt f a gt g f b 正如类型所示 如何获得 a gt b 应用于那个a在上下文中f 感谢帮助 这是关注类型很有帮助的情况
  • 为什么这会导致 Haskell Conduit 库内存泄漏?

    我有一个conduit https hackage haskell org package conduit管道处理长文件 我想每 1000 条记录为用户打印一份进度报告 所以我这样写 Every n records perform the
  • Haskell 单例:我们可以通过 SNat 获得什么

    我正在尝试使用 Haskell 单例 在论文中使用单例进行依赖类型编程 http cs brynmawr edu rae papers 2012 singletons paper pdf并在他的博客文章中单例 v0 9 发布 https t
  • 应用交换律

    带有效果的应用程序编程 http staff city ac uk ross papers Applicative html麦克布莱德和帕特森的论文提出了互换法 u lt gt pure x pure f gt f x lt gt u 为了
  • 计算/获取分层数据的“级别”

    好吧 我真的不知道这是否是正确的标题 但我不知道如何称呼它 我的问题是关于我的作业 我现在已经工作了几个小时 主题是 函数式数据结构 我有点陷入困境 我不知道如何继续 所以我需要编写一个具有以下签名的函数 data Heap e t Hea
  • Haskell 真的是纯粹的吗(有任何语言可以处理系统外的输入和输出)吗?

    在谈到函数式编程中的 Monad 后 该功能是否真的使语言变得纯粹 或者它只是黑板数学之外的现实世界中计算机系统推理的另一张 免狱卡 EDIT 这不是有人在这篇文章中所说的火焰诱饵 而是一个真正的问题 我希望有人能用它来击倒我并说 证明 它
  • 如何在 Haskell 中枚举递归数据类型?

    这篇博文 http lukepalmer wordpress com 2008 05 02 enumerating a context free language 对于如何使用 Omega monad 对角枚举任意语法有一个有趣的解释 他提
  • Haskell 二进制解析

    我一直在尝试在 haskell 中实现一个协议解析器 而且我对这门语言还很陌生 特别是当涉及到 monad 时 我一直在使用binary 0 5 0 2 并描述了协议的标头和所有有效负载 我想要解析的消息如下所示 header payloa
  • 'lens' 的阴谋集团依赖性解析失败

    我刚刚做了一个阴谋更新并尝试从 hackage 安装 lens 这给了我以下错误 cabal install j lens Resolving dependencies Configuring dlist 0 7 0 1
  • 谁能解释一下 GHC 对 IO 的定义吗?

    标题非常自我描述 但有一个部分引起了我的注意 newtype IO a IO State RealWorld gt State RealWorld a 剥离newtype 我们得到 State RealWorld gt State Real
  • 如何获取常量内存中的统计数据

    我有一个函数 它会创建一些随机的数值结果 我知道 结果将是 a 小 a b 约 50 范围内的整数a b 我想创建一个执行上述函数 1000000 次的函数 并计算每个结果出现的频率 该函数使用随机生成器来生成结果 问题是 我不知道如何在常
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 为什么haskell中的递归列表这么慢?

    我对 Haskell 很陌生 我在 Haskell 中定义了一个函数 febs Integral a gt a gt a febs n n lt 0 0 n 1 1 n 2 1 otherwise febs n 1 febs n 2 但是
  • 对元组列表进行排序的函数 - Haskell

    抱歉 这个简单的问题只是我对 haskell 非常陌生 我正在尝试编写一个函数 order 它将对另一个函数 Frequency 生成的元组列表进行排序 频率计算列表中不同元素的数量 a给出一个这样的结果 比如 gt 频率 aabbbccc
  • 反应性香蕉时间延迟

    我已经查阅了文档反应香蕉 http hackage haskell org package reactive banana 而且我找不到指定明确时间延迟的方法 举例来说 我想采取Event t a并将其所有发生的事件移至未来 1 秒 或获取
  • 有什么方法可以在 do / while / let 块中打印出变量的类型吗?

    有没有办法打印出嵌套变量的推断类型ghci 考虑代码 let f g where g x Int x 那么 最好查询一下类型g e g t f g会打印出Int gt Int 您可以通过给出适当的错误类型注释并检查错误消息来诱骗此信息 Ma
  • 我应该如何使 Clojure STM 程序持久化?

    我正在编写一个使用 STM 的 clojure 程序 目前 我在启动时从数据库填充 STM 使用引用 然后在 dosync 事务成功时异步更新数据库 我不知道我是否以正确的方式这样做 或者是否有更好的标准技术来做到这一点 谁能向我解释一下他
  • 简单的秒差距示例会产生类型错误

    我正在尝试编译这个简单的秒差距代码 import Text Parsec simple letter 但我不断收到此错误 No instance for Stream s0 m0 Char arising from a use of let
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将

随机推荐

  • 使用 jQuery 切换类

    当用户单击链接时 我需要隐藏 div html 是这样的 div class item div class entry Lorem ipsum div a href class commentsToggle Show hide commen
  • Ionic - 如何设置 高度,以便它在所有分辨率设备中自动调整?

    我的代码如下
  • 如何在关闭时完全删除对话框

    当 ajax 操作失败时 我创建一个包含错误的新 div 然后将其显示为对话框 当对话框关闭时 我想完全销毁并再次删除 div 我怎样才能做到这一点 我的代码目前看起来像这样 div We failed div dialog title E
  • 在Java中查找数组中的元素

    Java 是否有内置函数允许我线性搜索数组中的元素 还是必须只使用 for 循环 有一个contains列表的方法 所以你应该能够这样做 Arrays asList yourArray contains yourObject 警告 这可能不
  • Flutter - 英雄动画不适用于选项卡导航器

    我是颤振新手 我正在使用英雄小部件为浮动按钮制作动画 我有底部导航 我必须使用选项卡导航器打开页面 但英雄动画不起作用 我使用了所有可能的解决方案 但英雄动画仍然不适用于页面路由 这是我的代码片段 FloatingActionButton
  • 无法删除全局包

    尝试删除全局包 但似乎没有删除它 eslint v v1 10 3 npm uninstall eslint g sudo npm uninstall eslint g eslint v v1 10 3 sudo eslint v v1 1
  • 如何使用之前输入的值填充自定义结帐字段,例如默认的 WooCommerce 结帐字段?

    我使用以下代码添加了一个自定义字段 add action woocommerce before order notes bbloomer add custom checkout field function bbloomer add cus
  • 在python中读取15M行csv文件的有效方法

    对于我的应用程序 我需要读取多个文件 每个文件有 15 M 行 将它们存储在 DataFrame 中 并将 DataFrame 保存为 HDFS5 格式 我已经尝试过不同的方法 特别是具有 chunksize 和 dtype 规范的 pan
  • 获取调用者类

    我正在编写 Logger 并在自动添加类名时遇到问题 我从中调用了 print log 方法 例如这样的事情 class Logger def self print log string puts Time now strftime T c
  • 美国电话号码验证

    我有一个网站表单 需要输入美国电话号码以供后续使用 在这种情况下这是非常有必要的 我想尝试消除用户输入垃圾数据330 000 0000 我已经看到了第三方为您验证电话号码的一些选项 但是我不知道这是否是这种情况的最佳选择 但是 如果您使用过
  • PyQt 项目视图自定义拖放

    我正在 QTableView 中进行自定义拖放实现 当我拖动一个单元格并将其放在另一个单元格上时 我想根据拖动的内容和放置的位置手动更改模型中的一些数据 我怎样才能做到这一点 我已经阅读了所有 Qt 文档 但我完全迷失了 特别是通过拖放 C
  • Couchbase 中的存储桶密码

    我正在创建一个使用 springboot 和 Couchbase 进行反应式编程的演示项目 我在 application properties 文件中设置了以下属性 spring couchbase bootstrap hosts loca
  • APK 0(零)设备兼容性

    我正在生成一个要在商店上发布的 APK 它是现有应用程序的更新 上传到 Google Play Console 后 支持的 Android 设备 0 台设备 这是我的清单
  • vue js如何使用方法将数据从父组件、v-for循环列表传递到子组件

    我试图实现在子组件 模态组件 中显示每个项目收据数组的项目列表 但一直无法这样做 方法display receipts 是将receipts modal的数据值改为true 我可以在哪里放置 v bind 来传递数组 任何帮助深表感谢 Pa
  • 使用networkx从图中删除边

    我正在尝试转换DiGraph成n叉树并按层序或BFS显示节点 我的树与此类似 但更大 为简单起见 使用以下示例 G networkx DiGraph G add edges from n n1 n n2 n n3 G add edges f
  • 是否可以使用服务帐户访问Provisioning API?

    我的服务帐户范围是 https apps apis google com a feeds user https apps apis google com a feeds user 和 DriveScope DRIVE 我在我的服务帐户 ID
  • VS2015:警告MSB3884:找不到规则集文件

    将我的 WinForms VS2013 项目升级到 VS2015 后 我开始看到 MSB3884 找不到规则集文件 警告 Google 搜索发现了一篇 MSDN 文章 Stack Overflow 文章以及许多其他网站都指向了该文章 类似问
  • R可以识别Excel文件是否有注释单元格吗?

    我有一张 Excel 表格 xlsx 其中有一些注释的单元格 导入R后 R有什么办法可以识别注释的单元格吗 因为我必须仅对注释的单元格使用一些 if else 条件 Let s say we have this file test xlsx
  • 以逗号或分号分隔的自动完成文本框

    我想要一个TextBox支持自动完成 并允许用户输入以逗号或分号分隔的多个单词 并为每个单词提供建议 我有一个标准TextBox with textBox AutoCompleteCustomSource AddRange new appl
  • Haskell、通道、STM、线程、消息传递

    我正在尝试使用 Channels STM 在 Haskell 中实现消息传递 也许这是一个糟糕的想法 并且有更好的方法在 Haskell 中实现 使用消息传递 如果是这种情况 请告诉我 然而 我的探索提出了一些关于并发 Haskell 的基