Skip to content

Instantly share code, notes, and snippets.

@Philonous
Last active January 18, 2016 22:40
Show Gist options
  • Select an option

  • Save Philonous/b334c81018628fd6cfc8 to your computer and use it in GitHub Desktop.

Select an option

Save Philonous/b334c81018628fd6cfc8 to your computer and use it in GitHub Desktop.
module Experiment where
import Control.Monad.Trans
import Data.IORef
import Reactive.Banana
import Reactive.Banana.Frameworks
import System.IO.Unsafe (unsafePerformIO)
-- To simulate sodium as close as possible, we define a global network that we
-- then modify
{-# NOINLINE globalNetwork #-}
globalNetwork :: Handler (MomentIO a)
globalNetwork = unsafePerformIO $ do
(ah, trigger) <- newAddHandler
actuate =<< compile (do
globalExecuteEV <- fromAddHandler ah
_ <- execute globalExecuteEV
return () )
return trigger
sync :: MomentIO a -> IO a
sync f = do
ref <- newIORef Nothing
globalNetwork $ do
res <- f
liftIO . writeIORef ref $ Just res
mbRes <- readIORef ref
case mbRes of
Just res -> return res
Nothing -> error "Network hasn't written result to ref"
main = do
(bhv1, set1) <- sync $ newBehavior (0 :: Integer)
(bhv2, set2) <- sync $ newBehavior (0 :: Integer)
set1 3
set2 7
let sumB = (liftA2 (+) bhv1 bhv2)
print =<< sync (valueB sumB)
set1 5
print =<< sync (valueB sumB)
return ()
@HeinrichApfelmus
Copy link

Actually, this code may not work as intended: There is no guarantee that execute will actually execute the IO action if the Event is discarded as you do in line 19. During garbage collection, the runtime may decide to remove the result of execute altogether, as it has no "visible" effect.

This can be fixed by feeding the result into a reactimate, like this

e <- execute globalExecuteEV
reactimate $ return () <$ e

This way, the event e will never be discarded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment