What's the inital value of a trimmed behavior

56 views Asked by At

I have the following test program:

{-# LANGUAGE RankNTypes #-}
module Main where

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

main = do
    fShowRef <- newIORef (const (return ()))
    fNumRef <- newIORef (const (return ()))
    let
        netDesc :: forall t. Frameworks t => Moment t ()
        netDesc = do
            (eNum, fNum) <- newEvent
            (eShow, fShow) <- newEvent
            liftIO (writeIORef fShowRef fShow)
            liftIO (writeIORef fNumRef fNum)
            let beh = stepper 0 eNum
            behTrimmed <- trimB beh
            reactimate (printInitial behTrimmed <$ eShow)

    actuate =<< compile netDesc

    fNum <- readIORef fNumRef
    fNum 1
    fShow <- readIORef fShowRef
    fShow ()

printInitial :: AnyMoment Behavior Int -> IO ()
printInitial beh = do
    let
        netDesc :: forall t. Frameworks t => Moment t ()
        netDesc = do
            behNow <- now beh
            initVal <- initial behNow
            liftIO (print initVal)
    -- compiling is enough, I just want to see the initial value
    void (compile netDesc)

I expected this to print

1

but it prints

0

I am creating a network with two events. eNum is an event of Ints, eShow one of (). Whenever eShow is raised, printInitial is executed.

printInitial prints the initial value of the behavior trimB (stepper 0 eNum). I thought that trimB followed by now discards the history before the point at which the network description in which it is contained is compiled. This would mean that every time eShow is raised, a new behavior appears starting with the value of beh at that time. Apparently, that's not the case.

So,

  • what is the purpose of trimB?
  • is it possible to transform x :: Behavior t0 a to y :: Behavior t1 a such that initial y is the value of x at t1?
1

There are 1 answers

1
Heinrich Apfelmus On BEST ANSWER

Your intuition is (supposed to be) correct: trimB followed by now should return the current value of the Behavior.

However, your code has a serious problem: It uses a Behavior created in one network (compile) during the compilation of another network (second compile). The result of this is undefined — even though the types seem to work out! I'm sorry about that.

I have pondered about this for some time, and hoped that nobody would try this combination. In principle, it is possible to disallow this scenario via the type system, Unfortunately, this would mean a second phantom parameter, and I didn't want to increase the notational burden even further, so I left it at the "please don't do this" contract.


As for your question: trimB and trimE are only used for changing the starting time of a Behavior resp. an Event within one network to allow dynamic switching. Semantically, the trimB function even seems to be a no-op, but internally, it is necessary to trim it.