Reverse State monad的现实生活和有用的例子

问题描述 投票:8回答:1

反向状态monad是非常好的,令人兴奋的Haskell语言表达性和懒惰评价的例子。但要理解这个单子并不容易。此外,很难找到一些令人信服的现实生活中的例子,说明你可以使用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)

它已经有一些例子和用法,但我发现它们并不实用。

  1. Quora answer:很好地解释,甚至有现实生活中的使用示例,但没有代码,并不清楚使用RState是否是一个非常好的主意。
  2. Mindfuck:介绍这个很好的概念但是例子没用。没有人会这样写斐波那契数字。
  3. qazxsw poi:展示如何用qazxsw poi模仿qazxsw poi但是来吧。不是真正的生活例子:)

我也知道Kwang's Haskell Blog包但没有这个库的教程,文档示例真的很抽象,没有那么多人真正理解它。最接近我想要的是Writer,但它有RState的例子,而不仅仅是tardis。以及this tutorial

因此,我不是在寻找tardis现实生活模式,如果可能的话,我只对RState插图感兴趣。虽然我明白可能没有纯粹的this book reference用法样本。在那种情况下,使用tardis变换器或RState的最小例子就足够了。

有人在现实生活中使用过这个monad,或者是否有非常好用且有用的插图代码?

haskell lazy-evaluation state-monad
1个回答
5
投票

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

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

RState

这里,sendToFuture是普通状态“put”,sendToPast是反向时间“put”,recvFromPast是普通状态“get”,而recvFromFuture是反向时间“get”。所以RStateT是我们从我们的前任那里得到的事件(可能是另一个像这样的瓷砖)告诉我们现在我们关注的焦点tardis是我们从接班人那里得到的类似事件。我们跟踪我们何时使用'hold'来构建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 ,然后用它来控制键盘事件,这样我们就可以告诉我们的邻居他们只有在我们自己专注的时候才能获得焦点,并且在我运行子窗口小部件的位置中也使用了它,以便适当地过滤其输入事件。

我不确定在图书馆发布时我们实际上仍然会这样做,但到目前为止它似乎运作良好,我很高兴终于注意到这种结构可能是投入实际使用。

© www.soinside.com 2019 - 2024. All rights reserved.