gpt4 book ai didi

haskell - 反向状态单子(monad)的真实生活和有用的例子

转载 作者:行者123 更新时间:2023-12-04 04:20:49 24 4
gpt4 key购买 nike

Reverse State monad 是 Haskell 语言的表现力和惰性求值的非常好的和令人兴奋的例子。但是要理解这个单子(monad)并不容易。此外,真的很难找到一些令人信服的现实生活示例,说明使用 Reverse State monad 比使用该语言中的任何其他工具更容易做什么。

反向状态 monad 定义如下:

newtype RState s a = RState { runRState :: s -> (a,s) }

instance Monad (RState s) where
return x = RState $ (,) x
RState sf >>= f = RState $ \s ->
let (a, past) = sf future
(b, future) = runRState (f a) s
in (b, past)

它已经有一些示例和用法,但我觉得它们不太实用。
  • Quora answer : 解释清楚,甚至有真实的使用示例,但没有代码,不清楚使用 RState 是否真的是一个好主意.
  • Mindfuck : 介绍这个不错的概念,但例子没有用。没有人会这样写斐波那契数字。
  • Kwang's Haskell Blog : 显示如何 Writer可以用 RState 模拟但来吧。不是一个真实的例子:)

  • 我也知道 tardis 包但是没有这个库的教程,文档示例真的很抽象,没有多少人真正理解它。最接近我想要的是 this tutorial但它有 tardis 的示例,而不仅仅是 RState .以及 this book reference .

    因此我不是在寻找 tardis现实生活中的模式,我只对 RState 感兴趣如果可能的话。虽然我知道可能没有纯 RState 的样本用法。在这种情况下, RStateT 的最小示例变压器或 tardis已经足够好了。

    有人在现实生活中使用过这个 monad,还是有非常好的和有用的代码说明?

    最佳答案

    我已经知道这些 monad 十多年了,直到最近才看到它们的实际应用。它处于一个不寻常的环境中。我和一位同事正在通过“reflex”库使用函数式响应式(Reactive)编程,并且正在开发一个库来帮助构建终端图形应用程序。如果你熟悉'reflex-dom',它本质上是相似的,除了我们的基本 monad,而不是在 DOM 中一个接一个地放置后续小部件,而是只是将基于终端字符单元的“图像”堆叠在顶部彼此之间,并由用户明智地分割屏幕。我们想提供比这更好的东西,它会在一定程度上跟踪剩余的屏幕空间,并让用户在行和列中放置一些“图 block ”,这样一个 do-block 基本上对应于一个屏幕上的一列或一行图 block 。

    除了处理布局问题外,我们还希望磁贴能够管理键盘焦点,允许用户按 tab 键循环浏览它们,或者 shift-tab 键反转。正是在这里,向前和向后的时间状态单子(monad)转换器变得非常方便:我们可以让任一方向的当前状态成为一个事件(一个空元组)。每个图 block 可以向前一个和下一个小部件发送事件(并从它们接收事件),在小部件接收键盘焦点时通知小部件,因此应停止阻止按键到达其子小部件。如此示意性地,磁贴小部件看起来像:

    do rec focusP <- recvFromPast
    sendToPast shiftTabPress
    tabPress <- gate focused $ ... filter input Event for Tab keypresses ...
    shiftTabPress <- gate focused $ ... filter input Event for Shift-Tab ...
    focused <- hold False $ leftmost
    [ True <$ (focusP <> focusF)
    , False <$ (shiftTabPress <> tabPress) ]
    v <- ... run the child widget and do layout stuff ...
    sendToFuture tabPress
    focusF <- recvFromFuture
    return v

    这里,sendToFuture 是普通状态“put”,sendToPast 是逆时“put”,recvFromPast 是普通状态“get”,recvFromFuture 是逆时“get”。所以 focusP :: Event t ()是我们从我们的前任(可能是另一个像这样的图 block )那里得到的一个事件,它告诉我们现在有焦点,并且 focusF , 是我们从继任者那里收到的类似事件。我们使用“保持”来构建 focused :: Behavior t Bool 来跟踪我们何时拥有焦点。 ,然后用于门控键盘事件,以便我们确保告诉我们的邻居他们只有在我们自己集中注意力时才获得焦点,并且也用于我省略的我们正在运行子小部件的位置,为了适本地过滤其输入事件。

    我不确定在库发布时我们是否真的会这样做,但到目前为止它似乎运行良好,我很高兴终于注意到这种结构可能是投入实际使用。

    关于haskell - 反向状态单子(monad)的真实生活和有用的例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43712476/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com