“Behavior now” in FRP

前端 未结 2 1286
情歌与酒
情歌与酒 2021-01-11 21:40

In a previous SO question (Is it possible?: Behavior t [Behavior t a] -> Behavior t [a]) we were analyzing the existence of a Behavior join (to

2条回答
  •  被撕碎了的回忆
    2021-01-11 22:02

    (Author here.)

    First note, that the behaviorNow function is the monadic join.

    In reactive-banana-0.7, Behavior t is not a monad beause that would have serious consequences for efficiency.

    The first and most important problem is that behaviors can also be stateful. In conjunction with join, this would lead to time leaks. The main indication of problems is that the starting time t of the inner Behavior t is the same as the outer one. For instance, consider the program

    e  :: Event t Int
    b  :: Int -> Behavior t Int
    b x = accumB 0 $ (x+) <$ e
    
    bb :: Behavior t (Behavior t Int)
    bb = stepper (pure 0) $ b <$> e
    

    The behavior join bb would need to keep track of the whole history of the event e in order to perform the accumulation in the definition of b. In other words, the event e could never be garbage collected -- a time leak.

    A second problem is that internally, the implementation of Behavior t also includes an event that keeps track of when the behavior changes. However, a liberal use of the join combinator, for instance as implied by do notation, would lead to rather convoluted calculations to determine whether the behavior has changed or not. This is contrary to the reason for keeping track in the first place: efficiency by avoiding expensive calculations.


    The Reactive.Banana.Switch module offers various combinators that are cousins of the join function, but avoid the first problem with cleverly chosen types. In particular:

    • The switchB function is the most direct analogue of join.
    • The AnyMoment Identity type is similar to the Behavior type, but without state and without keeping track of changes. Consequently, it has a monad instance.

提交回复
热议问题