混合 Threepenny-Gui 和 StateT

2024-01-20

我有一个关于 Threepenny-Gui 与 StateT 交互的问题。 考虑这个玩具程序,每次单击按钮时,都会在列表中添加一个“Hi”项目:

import           Control.Monad
import           Control.Monad.State

import qualified Graphics.UI.Threepenny      as UI
import           Graphics.UI.Threepenny.Core hiding (get)

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup w = void $ do
  return w # set title "Ciao"
  buttonAndList <- mkButtonAndList
  getBody w #+ map element buttonAndList

mkButtonAndList :: UI [Element]
mkButtonAndList = do
  myButton <- UI.button # set text "Click me!"
  myList <- UI.ul
  on UI.click myButton $ \_ -> element myList #+ [UI.li # set text "Hi"]
  return [myButton, myList]

现在,我希望它打印自然数,而不是“Hi”。我知道我可以利用 UI monad 是 IO 包装器这一事实,并读取/写入我迄今为止在数据库中达到的数字,但是,出于教育目的,我想知道我是否可以使用StateT,或者通过 Threepenny-gui 界面访问列表的内容。


StateT在这种情况下不起作用。问题是您需要在按钮回调调用之间保持计数器的状态。由于回调(并且startGUI以及)生产UI行动,任何StateT使用它们运行的​​计算必须是独立的,以便您可以调用runStateT并利用所得结果UI action.

使用 Threepenny 有两种主要方法来保持持久状态。第一个也是最直接的方法是使用IORef http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-IORef.html(这只是一个可变变量,位于IO) 保持计数器状态。这会产生与使用传统事件回调 GUI 库编写的代码非常相似的代码。

import           Data.IORef
import           Control.Monad.Trans (liftIO)

-- etc.

mkButtonAndList :: UI [Element]
mkButtonAndList = do
  myButton <- UI.button # set text "Click me!"
  myList <- UI.ul

  counter <- liftIO $ newIORef (0 :: Int) -- Mutable cell initialization.

  on UI.click myButton $ \_ -> do
    count <- liftIO $ readIORef counter -- Reads the current value.
    element myList #+ [UI.li # set text (show count)]
    lift IO $ modifyIORef counter (+1) -- Increments the counter.

  return [myButton, myList]

第二种方式是从命令式回调接口切换到声明式 FRP 接口Reactive.Threepenny http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Reactive-Threepenny.html.

mkButtonAndList :: UI [Element]
mkButtonAndList = do
  myButton <- UI.button # set text "Click me!"
  myList <- UI.ul

  let eClick = UI.click myButton  -- Event fired by button clicks.
      eIncrement = (+1) <$ eClick -- The (+1) function is carried as event data.
  bCounter <- accumB 0 eIncrement -- Accumulates the increments into a counter.

  -- A separate event will carry the current value of the counter.
  let eCount = bCounter <@ eClick
  -- Registers a callback.
  onEvent eCount $ \count ->
    element myList #+ [UI.li # set text (show count)]

  return [myButton, myList]

典型用法Reactive.Threepenny是这样的:

  • 首先,你要掌握一个Event从用户输入通过Graphics.UI.Threepenny.Events http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Graphics-UI-Threepenny-Events.html (or domEvent http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Graphics-UI-Threepenny-Core.html#v:domEvent,如果您选择的事件不包含在该模块中)。这里,“原始”输入事件是eClick.
  • 然后,您可以使用以下方式按摩事件数据Control.Applicative and Reactive.Threepenny组合器。在我们的例子中,我们转发eClick as eIncrement and eCount,在每种情况下设置不同的事件数据。
  • 最后,您可以通过构建一个来使用事件数据Behavior (like bCounter)或回调(通过使用onEvent http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Graphics-UI-Threepenny-Core.html#v:onEvent) 出来。行为有点像可变变量,只不过对它的更改是由事件网络以原则性的方式指定的,而不是通过散布在代码库中的任意更新来指定的。用于处理此处未显示的行为的有用函数是sink http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Graphics-UI-Threepenny-Core.html#v:sink函数,它允许您将 DOM 中的属性绑定到行为的值。

中提供了另一个示例以及对这两种方法的更多评论这个问题 https://stackoverflow.com/q/20872825/2751851以及阿普费尔姆斯对此的回答。


细节:在 FRP 版本中您可能关心的一件事是是否eCount将得到的值bCounter在更新触发之前或之后eIncrement。答案是,该值肯定会是旧值,正如预期的那样,因为,正如所提到的Reactive.Threepenny文档,Behavior更新和回调触发有一个名义上的延迟,而其他延迟则不会发生Event操纵。

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

混合 Threepenny-Gui 和 StateT 的相关文章

  • 这个记忆的斐波那契函数是如何工作的?

    在我正在做的函数式编程课程的当前练习作业中 我们必须制作给定函数的记忆版本 为了解释记忆化 给出以下示例 fiblist fibm x x lt 0 fibm 0 0 fibm 1 1 fibm n fiblist n 1 fiblist
  • 如何手动推断表达式的类型

    给定 Haskell 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名
  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • Haskell:是的,没有类型类。为什么是整数?

    我有一个关于 GHCi 如何假定整数类型的问题 我正在阅读 Learn you a Haskell 是 否类型的课程 如果您想阅读全文 这里有一个链接 http learnyouahaskell com making our own typ
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • Haskell - 用防护罩替换外壳

    我想知道在这部分代码中是否可以用守卫替换 case 语句 firstFunction String gt Maybe MyType secondFunction MyType gt Integer myFunction String gt
  • Haskell 泛化问题(涉及列表理解)

    假设我想知道a上的所有要点 x y 矩形内的平面has 我可以使用列表推导式来计算 如下所示 let myFun2D x y x lt 0 2 y lt 0 2 现在 如果我想为一个人完成同样的事情 x y z 空间 我可以采取同样的方式并
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • 标准的能力

    我发现了一些使用标准的旧例子here http www serpentine com blog 2009 09 29 criterion a new benchmarking library for haskell 看起来好像早在 2009
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • 检查对以下内容的理解:“变量”与“变量” “价值”、“功能”与“抽象”

    这个问题是后续问题this one https stackoverflow com questions 25327705 is function a sort of variable 25329157 25329157在学习 Haskell
  • 不同编程语言中的浮点数学

    我知道浮点数学充其量可能是丑陋的 但我想知道是否有人可以解释以下怪癖 在大多数编程语言中 我测试了 0 4 到 0 2 的加法会产生轻微的错误 而 0 4 0 1 0 1 则不会产生错误 两者计算不平等的原因是什么 在各自的编程语言中可以采
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre
  • 如何打乱列表?

    如何从一组数字 1 2 3 直到我击中x 我的计划是重新调整列表 1 2 3 并把它砍在x chopAt 3 2 3 1 2 3 chopAt 3 2 1 3 2 1 3 chopAt 3 3 1 2 3 chopAt chopAt x y
  • 关于“没有绑定的类型签名”的错误

    我在 Haskell 中遇到 ASCII 问题 fromEnum Char gt Int toEnum Int gt Char offset Int offset fromEnum A fromEnum a toUpper Char gt
  • 约束包如何工作?

    背后的想法数据 约束 Forall http hackage haskell org packages archive constraints 0 3 2 doc html src Data Constraint Forall html据我
  • Haskell 项目可以使用 cmake 吗?

    我正在计划一个用 Haskell 编写的项目 也许也有一些部分是用 C 编写的 对于构建系统 我决定不选择 Haskell 程序 cabal 的常见选择 主要是因为我想了解其他语言的构建程序是如何工作的 我听说过 CMake 我认为这是一个
  • 树莓派 2 上的 GHCi?

    我正在开发一些在 raspberry pi 2 上运行的 haskell 项目 以及可以使用 raspbian 7 4 1 中的 apt get 安装的 ghc 版本 但它没有 GHCi 这会阻止一些重要的包 如 Vector 的编译 我看
  • Parsec.Expr 具有不同优先级的重复前缀

    Parsec Expr buildExpressionParser 的文档说 相同优先级的前缀和后缀运算符只能出现一次 即 如果 为前缀否定 则不允许使用 2 但是 我想解析这样的字符串 具体来说 考虑以下语法 sentence ident

随机推荐

  • MPMoviePlayerController 音频显示“完成”按钮

    我使用 MPMoviePlayerController 来播放音频流 我的代码遵循以下示例 http iosdevelopertips com video getting mpmovieplayercontroller to coopera
  • 如何使用 Node.js 将文件从一台服务器传输到另一台服务器

    如果在其他地方问过这个问题 我很抱歉 但我找不到合适的解决方案来解决这个令人烦恼的问题 所以这就是我的情况 我有一个 node js 脚本 它从头开始创建一个 Excel 文档 一切都按预期工作 但是 我无法将这个新创建的文件保存到另一个运
  • onBackPressed 将数据发送到父活动[重复]

    这个问题在这里已经有答案了 有没有办法在按下后退时将更新的数据发送到父活动 我想更新捆绑包中的数据 但我不知道如何访问它 例如 我有一个打开图像查看器的画廊活动 假设用户滚动浏览十几张图像 然后返回到图库 理想的做法是使用他们最后查看的图像
  • Rust 有没有办法用索引折叠?

    在 Ruby 中 如果我有一个数组a 1 2 3 4 5 我想得到每个元素乘以它的索引的总和 a each with index inject 0 s i j s i j 在 Rust 中是否有一种惯用的方法可以做同样的事情 到目前为止 我
  • 使用 nghandsontable 访问 Handsontable 方法/属性

    我在用着ngHandson表 https github com handsontable ngHandsontable角度指令手动表 http handsontable com 我成功地显示了数据 但我正在努力访问修改后的行 以便将数据发送
  • 将对象转换为 类型

    我正在实现一个类的 List 接口 该类将数据存储在
  • iOS 自定义地图、地理位置、地图绘制等

    下一张图片取自 www Trimaps com 我希望这里允许使用图片 如果不允许 请告诉我 我会立即删除 这些图像完美地解释了我想要实现的目标 我拥有所需的所有数据 所需区域 4 个角的纬度 经度 以十进制值表示 来自 Google 地图
  • Clojure:在嵌套哈希图中搜索 val 并返回包含该 val 的键序列的函数

    假设我们有一个包含嵌套数据结构的集合 def coll a aa b d dd e f h hh i ii g gg c cc 我想创建一个函数 在嵌套结构中的任何位置搜索 val 并返回包含该 val 的键序列 search parent
  • 使用 Bootstrap ScrollSpy 将 div 折叠到固定的侧边栏

    我将此代码作为页面的布局 span9 div 包含应应用滚动间谍的部分 每个部分都是一组包含实际内容的可折叠 div span3 div 是固定的侧边栏 必须使用滚动间谍突出显示正确的项目 div class span3 module si
  • iOS 配置文件在 6 天后过期

    我是 iOS 开发新手 因为我目前只为 Android 开发 我遇到了一个问题 我一直在寻找可能的解决方案 我想做一个个人 iOS 应用程序 比如个人笔记应用程序或个人提醒应用程序等 我成功了 唯一的问题是配置文件仅持续 6 天 我认为 并
  • iPhone 5屏幕尺寸VS CSS媒体查询[重复]

    这个问题在这里已经有答案了 可能的重复 iPhone 5 CSS 媒体查询 https stackoverflow com questions 12539697 iphone 5 css media query iPhone 5 技术规格规
  • 如何生成一个随机数,然后将其显示在屏幕上?

    好吧 我对 Android 相当陌生 但我已经设法自学了基础知识 我正在制作一个应用程序 您按下一个按钮 就会打开一个新屏幕 它会显示一个随机生成的数字 唯一的问题是我不知道如何生成并显示随机数 我已经在网络上搜索了很长时间 只找到了很少的
  • UITextView 偏移文本的方式与 UILabel 不同

    我在用UILabel and UI文本视图并且它们以不同的方式呈现文本 看起来UI文本视图将文本偏移 4 下面是一个例子 其中顶部是UILabel下面是UI文本视图 他们都使用相同的字体 这里有两个例子 一个是自定义的OpenSans字体和
  • 在 iOS16 中以编程方式推送 NavigationLink

    在以前的 iOS 版本中 我以编程方式推送了一个 NavigationLink NavigationLink isActive searched destination SearchView originalSearchPhrase sea
  • 是否可以设置 html5 音频标签的样式?

    我还没有找到任何关于如何做到这一点的资源 像改变播放器颜色这样简单的事情就很好了 是的 您可以隐藏内置浏览器 UI 通过删除controls属性来自audio 而是构建您自己的界面并使用 Javascript 控制播放 source htt
  • Angular 如何根据路线更改导航菜单标题

    我正在使用 Angular 4 在当前项目中开发仪表板布局 当用户在应用程序的不同部分之间导航时 我需要更新导航菜单标题标题以反映应用程序的当前部分 例如 当用户访问设置时 页面标题 应更改为 设置 该项目基于 net core 2 Ang
  • 突变残基和位置的数字编码

    我正在编写一个 python 程序 它必须计算突变残基和位置的数字编码一组字符串 这些字符串是蛋白质序列 这些序列存储在 fasta 格式文件中 每个蛋白质序列用逗号分隔 不同蛋白质的序列长度可能不同 在此我试图找到以下位置和序列 变异了
  • wordpress 在functions.php第5行中的非对象上调用成员函数add_section()

    嘿 我对 php 和 WordPress 开发有点陌生 我只是在尝试 WordPress 的工作原理以及主题的工作原理 现在我已经尝试多次查找此内容但没有帮助 总是有一些不同的东西 对那些人有用的东西 对我不起作用 这是代码
  • Android Compose 创建摇动动画

    我正在尝试在 Jetpack Compose 中制作形状的晃动动画 我想在用户输入无效的 Pin 码时使用此动画来显示错误 但我能找到的只是滑入 滑出动画和一些缩放动画 我有什么想法可以做到这一点吗 Update 在 Thracian 回答
  • 混合 Threepenny-Gui 和 StateT

    我有一个关于 Threepenny Gui 与 StateT 交互的问题 考虑这个玩具程序 每次单击按钮时 都会在列表中添加一个 Hi 项目 import Control Monad import Control Monad State i