[reactive] Re: Re: Link to Tetris

Thomas Davie tom.davie at gmail.com
Tue Dec 16 05:56:35 EST 2008


On 16 Dec 2008, at 11:50, Claus Reinke wrote:

>>> Seems to be partially timer- and partially event-merge-related:
>>> if I compile with -threaded, the pieces do not move at all on their
>>> own, but as long as I keep pressing "down", the game appears
>>> playable as intended; if I compile without -threaded, the pieces
>>> move occasionally, but the effects of keyboard input are entirely
>>> unpredictable.
>>
>> I've noticed this behavior in since the last couple of days, So at  
>> a  guess a bug got introduced
>> somewhere along the line.  The merge issue  is known -- at the  
>> moment, an occurrence doesn't
>> appear in the output  until it's known whether or not the other  
>> event ever occurs, which  isn't
>> ideal.  Unfortunately, the obvious fix for the issue creates a   
>> large memory leak, I've been
>> playing with a few ways to fix this.
>
> Thanks for the info, Tom,
>
> where can I find more details about this merge issue? Given that
> FRPLs are traditionally synchronously concurrent languages, this
> is rather surprising: when sampling anything, one knows about
> everything's values _now_, which should be sufficient for merge,
> no matter whether the other event might or might not happen later.

Yes indeed.  The issue is that if you know one of the events will  
never happen again, what you want to do is stop merging, and throw the  
never-occurring event in the bin.  Unfortunately, to pattern match  
against the never occurring event then blocks checking whether the  
match works or not :(.  The particular interesting bit of code is in  
PrimReactive.hs (Conal's comments here):

-- | Merge two 'Future' streams into one.
merge :: Ord t => Binop (FutureG t (ReactiveG t a))

-- The following two lines seem to be too strict and are causing
-- reactive to lock up.  I.e. the time argument of one of these
-- must have been _|_, so when we pattern match against it, we 
-- block.
-- 
-- On the other hand, they patch a massive space leak in filterE.   
Perhaps
-- there's an unamb solution.

Future (Max MaxBound,_) `merge` v = v
u `merge` Future (Max MaxBound,_) = u

u `merge` v =
   (inFutR (`merge` v) <$> u) `mappend` (inFutR (u `merge`) <$> v)

-- What's going on in this 'merge' definition?  Try two different
-- future paths.  If u arrives before v (or simultaneously), then
-- begin as u begins and then merge v with the rest of u.  Otherwise,
-- begin as v begins and then merge u with the rest of v.  Because of
-- the left-bias, make sure u fragments are always the first argument
-- to merge and v fragments are always the second.


Bob


More information about the Reactive mailing list