Open divipp opened 9 years ago
I checked the corresponding expression in the pure implementation:
starts = let
c = head $ start $ do
c <- stateful 0 (+1)
return $ pure c
in head $ start $ do
c2 <- stateful 0 (+1)
return $ liftM2 (+) c c2
This evaluates to 0
.
I went on examining the issue. I have made another test case which may give further insight:
starts' = do
smp1 <- start $ do
s <- stateful 'a' succ
return $ ((,) s) <$> s
(s, a1) <- smp1
smp2 <- start $ transfer "" (:) s
b1 <- smp2
(s, a2) <- smp1
(s, a3) <- smp1
b2 <- smp2
b3 <- smp2
(s, a4) <- smp1
b4 <- smp2
print ([a1, a2, a3, a4], [b1, b2, b3, b4])
The corresponding pure expression is
starts'' = let
as = start $ do
s <- stateful 'a' succ
return $ ((,) s) <$> s
s = fst $ head as
bs = start $ transfer "" (:) s
in (take 4 $ map snd as, take 4 bs)
Results:
starts' --> ("abcd",["b","db","ddb","eddb"])
starts'' --> ("abcd",["a","ba","cba","dcba"])
My thoughts:
The output of starts'
is at least counterintuitive.
During the transformation to the pure semantics, the information about the sampling order is lost.
Because of this, the interface of FRP.Elerea.Simple.Pure
is insufficient to describe some meaningful sematics of entangled start
calls.
Enangled start
calls could be prevented by phantom type variables in compile time but that would be an overkill. Runtime errors might be feasible though.
I think it is possible to give meaningful semantics to entangled start
calls. What would be the benefit of this? Entangled start
calls (with an easier-to-use interface) might be an alternative to clocked elerea networks.
Just for reference, here’s the first example with strings:
starts = do
c <- join $ start $ do
c <- stateful "a" ('a':)
return $ pure c
join $ start $ do
c2 <- stateful "b" ('b':)
return $ liftM2 (++) c c2
This returns "aab"
, i.e. we’re observing the second output of the first signal. This is not totally unexpected, since the documentation states that the sampling action created by start
updates the network. Observing the inner state of the network between two samplings is undefined behaviour.
Nevertheless, it would be certainly nice if signals could be used in this manner. To allow this, the superstep should be redefined so the sampling and updating phases are swapped. The first step would have to start with a dummy update that doesn’t really do anything. I think this could be accomplished by defining a distinguished starting state for signals.
starts
below returns1
instead of0
:Intuitively, the first
start
creates a counter andjoin
do one sampling. Because no other sampling will ever happen, the value of this counter should be0
in any computation. Then the secondstart
creates another counter andjoin
do one sampling. Moreover, the secondstart
combines the values of the counters which sould be0
.