gpt4 book ai didi

events - 事件处理程序堆栈

转载 作者:行者123 更新时间:2023-12-02 09:25:21 24 4
gpt4 key购买 nike

我想实现一堆可以在事件中交换的对象。在接收到上方或下方的事件表单后,对象可以向以太端发出其他事件或更改状态(但保留其在堆栈中的位置)。

目前我有这个工作。我有一个类型 Animation a b它是事件处理程序的容器,它接收(从上面)类型为 a 的事件并发出(向上)类型为 b 的事件我有一个函数handle :: Handler -> Animation g h -> Animation e f堆叠它们。
Handler 的实际类型是

Animation g h -> (Either e h) -> 
WriterT [Either g f] IO (Either (Animation e f) (Animation g h))

这里 (Either e h)是来自上方或下方的事件, [Either g f]是向下还是向上发出的事件和 Either (Animation e f) (Animation g h)是作为独立对象或使用相同处理程序的结果。而我并不快乐。

有没有更优雅的方法来做到这一点?

最佳答案

这正是 Proxypipes 输入做。从图形上看,它看起来有点像这样:

 Upstream | Downstream
+---------+
| |
a' <== <== b'
| |
a ==> ==> b
| | |
+----|----+
v
r

它有两个接口(interface):上游接口(interface)和下游接口(interface)。它在两个接口(interface)上发送和接收信息。这类似于堆栈中的一个层,其中“上游”可能是它上面的堆栈帧,“下游”可能是它下面的堆栈帧。

要与上游接口(interface)通信,请使用 request ,它有这种类型:
request :: Monad m => a' -> Proxy a' a b' b m a

换句话说, request发送 a' 类型的值上游并等待 a 类型的响应.
request 的对偶是 respond ,它在下游接口(interface)上进行通信:
respond :: Monad m => b -> Proxy a' a b' b m b'
respond发送 b 类型的值下游并等待 b' 类型的响应.

一个 Proxy可以处于三种状态之一。它可以是:
  • 等待上游响应

  • 它的类型将表明它正在等待 a :
    waitingUp :: a -> Proxy a' a b' b m r
  • 等待下游响应:

  • 它的类型表明它正在等待 b' :
    waitingDn :: b' -> Proxy a' a b' b m r
  • 当前处于事件状态,无需等待:

  • 它的类型表明它不等待任何值:
    notWaiting :: Proxy a' a b' b m r

    有四种方法可以连接这三种状态:
  • 连接 Proxy在下游等待事件 Proxy ,这会生成一个新的事件 Proxy .

  • 这就是 (+>>)运营商:
    (+>>)
    :: Monad m
    => (b' -> Proxy a' a b' b m r) -- Waiting on downstream
    -> Proxy b' b c' c m r -- Active
    -> Proxy a' a c' c m r -- Active
  • 连接一个活跃的ProxyProxy在上游等待,这会生成一个新的事件 Proxy .

  • 这就是 (>>~)运营商:
    (>>~)
    :: Monad m
    => Proxy a' a b' b m r -- Active
    -> (b -> Proxy b' b c' c m r) -- Waiting on upstream
    -> Proxy a' a c' c m r -- Active
  • 连接两个 Proxy都在上游等待的 s,以生成新的 Proxy等待上游。

  • 这就是 (>~>)运营商:
    (>~>)
    :: Monad m
    => (a -> Proxy a' a b' b m r) -- Waiting on upstream
    -> (b -> Proxy b' b c' c m r) -- Waiting on upstream
    -> (a -> Proxy a' a c' c m r) -- Waiting on upstream
  • 连接两个 Proxy都在下游等待的 s,以生成新的 Proxy等待下游。

  • 这就是 (>+>)运营商:
    (>+>)
    :: Monad m
    => (b' -> Proxy a' a b' b m r) -- Waiting on downstream
    -> (c' -> Proxy b' b c' c m r) -- Waiting on downstream
    -> (c' -> Proxy a' a c' c m r) -- Waiting on downstream

    这是以这种方式实现和连接的三个堆栈帧的示例。我将使用堆栈从上游开始的约定,尽管实现是完全对称的,如果您愿意,可以使用相反的约定:
    import Pipes.Core
    import Pipes

    -- +-+-- Closed upstream interface
    -- | |
    -- v v
    up :: () -> Proxy X () String Int IO ()
    up () = do
    str1 <- respond 4
    lift (putStrLn str1)
    str2 <- respond 5
    lift (putStrLn str2)

    middle :: Int -> Proxy String Int Double Char IO ()
    middle int = do
    lift (print int)
    double <- respond (head (show int))
    lift (print double)
    int' <- request (show double)
    middle int'

    -- Closed downstream interface --+-+
    -- | |
    -- v v
    down :: Char -> Proxy Double Char () X IO ()
    down char1 = do
    lift (print char1)
    char2 <- request (1.0)
    lift (print char2)
    char3 <- request (2.0)
    lift (print char3)

    -- +-+--+--+-- Everything closed
    -- | | | |
    -- v v v v
    total :: () -> Proxy X () () X IO ()
    total = up >~> middle >~> down

    main :: IO ()
    main = runEffect $ total ()

    这会产生以下输出:
    >>> main
    4
    '4'
    1.0
    1.0
    5
    '5'
    2.0
    2.0

    尝试手动跟踪执行路径,从 up 开始 Proxy .每次 up respond s 有一个值,将控制权交给 middle ,并且每次 middle respond具有将控制权交给 down 的值.反之亦然,每次 down request s 一个值,将控制权交给 middle ,并且每次 middle request s 将控制权交给 up 的值.如果链中的任何管道终止,则整个链终止。

    编辑:要回答您的问题,是的,您可以根据结果更改行为。只需写 middle像这样:
    middle :: Int -> Proxy String Int Double Char IO ()
    middle int = do
    lift (print int)
    double <- respond (head (show int))
    case double of
    0.0 -> foo
    _ -> bar

    ...在哪里 foobar都是 Proxy s 具有与 middle 相同的输入和输出:
    foo :: Proxy String Int Double Char IO ()

    bar :: Proxy String Int Double Char IO ()

    当您对两个 Proxy 进行排序时s,第二个 Proxy从第一个 Proxy 开始结束。您不仅限于对 request 等原始命令进行排序。和 respond .您可以调用任何 Proxy将任意数量的步骤作为一个较大的 Proxy 中的子程序只要它共享相同的上下游接口(interface)。

    关于events - 事件处理程序堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23185690/

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