Подтвердить что ты не робот

Выборка из внешней сети

Так как натрий был устарел автором, я пытаюсь перенести свой код на реактивно-банановый. Тем не менее, похоже, есть некоторые несоответствия между этими двумя, у меня тяжелое переполнение.

Например, в натрие было легко получить текущее значение поведения:

retrieve :: Behaviour a -> IO a
retrieve b = sync $ sample b

Я не вижу, как это сделать в реактивном банане

(Причина, по которой я хочу это, заключается в том, что я пытаюсь экспортировать поведение в качестве свойства dbus. Свойства могут запрашиваться у других клиентов dbus)

Изменить: заменил слово "опрос", поскольку оно вводило в заблуждение

4b9b3361

Ответ 1

Ответ, кажется, "это возможно".

образец соответствует valueB, но там не является прямым эквивалентом sync.

Однако он может быть повторно реализован с помощью execute:

module Sync where

import Control.Monad.Trans
import Data.IORef
import Reactive.Banana
import Reactive.Banana.Frameworks

data Network = Network { eventNetwork :: EventNetwork
                       , run :: MomentIO () -> IO ()
                       }

newNet :: IO Network
newNet = do
    -- Create a new Event to handle MomentIO actions to be executed
    (ah, call) <- newAddHandler
    network <- compile $ do
        globalExecuteEV <- fromAddHandler ah
        -- Set it up so it executes MomentIO actions passed to it
        _ <- execute globalExecuteEV
        return ()
    actuate network
    return $ Network { eventNetwork = network
                     , run = call -- IO Action to fire the event
                     }

-- To run a MomentIO action within the context of the network, pass it to the
-- event.
sync :: Network -> MomentIO a -> IO a
sync Network{run = call} f = do
    -- To retrieve the result of the action we set up an IORef
    ref <- newIORef (error "Network hasn't written result to ref")
    -- (`call' passes the do-block to the event)
    call $ do
        res <- f
        -- Put the result into the IORef
        liftIO $ writeIORef ref res
    -- and read it back once the event has finished firing
    readIORef ref

-- Example
main :: IO ()
main = do
    net <- newNet -- Create an empty network
    (bhv1, set1) <- sync net $ newBehavior (0 :: Integer)
    (bhv2, set2) <- sync net $ newBehavior (0 :: Integer)
    set1 3
    set2 7
    let sumB = (liftA2 (+) bhv1 bhv2)
    print =<< sync net (valueB sumB)
    set1 5
    print =<< sync net (valueB sumB)
    return ()

Ответ 2

Если у вас есть поведение, моделирующее значение вашего свойства, и у вас есть событие, моделирующее входящие запросы для значения свойства, то вы можете просто использовать (<@) :: Behavior b -> Event a -> Event b 1 чтобы получить новое событие возникающие во время ваших входящих запросов со значением, которое имеет свойство в то время). Затем вы можете преобразовать это в действительные действия ввода-вывода, которые необходимо предпринять, чтобы ответить на запрос и использовать reactimate, как обычно.


1https://hackage.haskell.org/package/reactive-banana-1.1.0.0/docs/Reactive-Banana-Combinators.html#v:-60--64-

Ответ 3

Для концептуальных/архитектурных причин, Reactive Banana имеет функции от Event до Behavior, но не наоборот, и это тоже имеет смысл, учитывая природу и значение FRP. Я уверен, что вы можете написать функцию опроса, но вместо этого вам следует рассмотреть возможность изменения базового кода, чтобы выставлять события.

Есть ли причина, по которой вы не можете изменить Behavior на Event? Если нет, это будет хороший способ решить вашу проблему. (Возможно, теоретически даже покажет недостаток дизайна, о котором вы уже не замечали.)