packages feed

sodium 0.6.0.2 → 0.7.0.0

raw patch · 6 files changed

+88/−16 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ FRP.Sodium: split :: Event [a] -> Event a
+ FRP.Sodium.Context: split :: Context r => Event r [a] -> Event r a

Files

examples/games/poodle.hs view
@@ -4,7 +4,7 @@ --     stb-image --     OpenGL --     GLUT-import FRP.Sodium+import FRP.Sodium hiding (split) import Control.Applicative import Control.Monad.Trans import Data.Maybe
examples/tests/unit-tests.hs view
@@ -526,12 +526,36 @@     unlisten     assertEqual "coalesce1" [2, 11] =<< readIORef outRef +split1 = TestCase $ do+    outRef <- newIORef []+    (ea, pushA) <- sync newEvent+    let ewords = coalesce (++) $ split $ words <$> ea+    unlisten <- sync $ listen ewords $ \o -> modifyIORef outRef (++ [o])+    sync $ pushA "the common cormorant"+    sync $ pushA "or shag"+    unlisten+    assertEqual "split1" ["the","common","cormorant","or","shag"] =<< readIORef outRef++split2 = TestCase $ do+    outRef <- newIORef []+    (ea, pushA) <- sync newEvent+    let halve []  = []+        halve [_] = []+        halve str = [take (length str `div` 2) str,+                     drop (length str `div` 2) str]+        ehalves = split $ (halve <$> ea) `merge` (halve <$> ehalves)+    unlisten <- sync $ listen ehalves $ \o -> modifyIORef outRef (++ [o])+    sync $ pushA "abcdefgh"+    unlisten+    assertEqual "split2" ["abcd","ab","a","b","cd","c","d",+                          "efgh","ef","e","f","gh","g","h"] =<< readIORef outRef+ tests = test [ event1, fmap1, merge1, filterJust1, filterE1, gate1, beh1, beh2, beh3, beh4, beh5,     behConstant, valuesThenMap, valuesTwiceThenMap, valuesThenCoalesce, valuesTwiceThenCoalesce,     valuesThenSnapshot, valuesTwiceThenSnapshot, valuesThenMerge, valuesThenFilter,     valuesTwiceThenFilter, valuesThenOnce, valuesTwiceThenOnce, valuesLateListen,     holdIsDelayed, appl1, snapshot1, count1, collect1, collect2, collectE1, collectE2, switchE1,-    switch1, once1, once2, cycle1{-, mergeWith1, mergeWith2, mergeWith3,+    switch1, once1, once2, cycle1, split1, split2 {-, mergeWith1, mergeWith2, mergeWith3,     coalesce1-} ]  main = {-forever $ -} runTestTT tests
sodium.cabal view
@@ -1,5 +1,5 @@ name:                sodium-version:             0.6.0.2+version:             0.7.0.0 synopsis:            Sodium Reactive Programming (FRP) System description:            A general purpose Reactive Programming (FRP) system. This is part of a project to@@ -20,15 +20,28 @@   .   See the /examples/ directory for test cases and examples.   .-  Changes: 0.2.0.0 Fix some value recursion deadlocks and improve docs;-           0.3.0.0 Add mergeWith, make cross asynchronous;-           0.4.0.0 API revamp to remove an excess type variable. Parallelism stuff to be rethought;-           0.5.0.0 Improved tests cases + add Freecell example, API tweaks;-           0.5.0.1 Internal improvements;-           0.5.0.2 Fix multiple memory leaks;-           0.6     Minor API changes, particular with accum;-           0.6.0.1 ghc-7.8 compatibility;-           0.6.0.2 Fix memory leak - see memory-test-8 & memory-test-8a.+  Changes:+  .+   * 0.2.0.0 - Fix some value recursion deadlocks and improve docs;+  .+   * 0.3.0.0 - Add mergeWith, make cross asynchronous;+  .+   * 0.4.0.0 - API revamp to remove an excess type variable. Parallelism stuff to be rethought;+  .+   * 0.5.0.0 - Improved tests cases + add Freecell example, API tweaks;+  .+   * 0.5.0.1 - Internal improvements;+  .+   * 0.5.0.2 - Fix multiple memory leaks;+  .+   * 0.6     - Minor API changes, particular with accum;+  .+   * 0.6.0.1 - ghc-7.8 compatibility;+  .+   * 0.6.0.2 - Fix memory leak - see memory-test-8 & memory-test-8a;+  .+   * 0.7.0.0 - Add split primitive.+ license:             BSD3 license-file:        LICENSE author:              Stephen Blackheath
src/FRP/Sodium.hs view
@@ -55,6 +55,7 @@         sample,         coalesce,         once,+        split,         -- * Derived FRP functions         mergeWith,         filterE,
src/FRP/Sodium/Context.hs view
@@ -82,6 +82,12 @@     coalesce      :: (a -> a -> a) -> Event r a -> Event r a     -- | Throw away all event occurrences except for the first one.     once          :: Context r => Event r a -> Event r a+    -- | Take each list item and put it into a new transaction of its own.+    --+    -- An example use case of this might be a situation where we are splitting+    -- a block of input data into frames. We obviously want each frame to have+    -- its own transaction so that state is updated separately each frame.+    split         :: Event r [a] -> Event r a  -- | A time-varying value, British spelling. type Behaviour r a = Behavior r a
src/FRP/Sodium/Plain.hs view
@@ -24,7 +24,7 @@ import Data.Maybe import Data.Set (Set) import qualified Data.Set as S-import Data.Sequence (Seq, (|>))+import Data.Sequence (Seq, (|>), (><)) import qualified Data.Sequence as Seq import GHC.Exts import System.Mem.Weak@@ -126,6 +126,7 @@     sample = sample     coalesce = coalesce     once = once+    split = split  -- | An event that gives the updates for the behavior. If the behavior was created -- with 'hold', then 'changes' gives you back the event that was passed to 'hold'.@@ -164,6 +165,13 @@                             loop                           else                             return ()+            post <- gets asPost+            unless (Seq.null post) $ do+                let Reactive task = post `Seq.index` 0+                modify $ \as -> as { asPost = Seq.drop 1 post }+                task+                loop+     outVar <- newIORef undefined     let lock = paLock partition     putMVar lock ()@@ -171,7 +179,8 @@     evalStateT loop $ ReactiveState {             asQueue1 = Seq.singleton (task >>= ioReactive . writeIORef outVar),             asQueue2 = q,-            asFinal = Seq.empty+            asFinal = Seq.empty,+            asPost = Seq.empty         }     takeMVar lock     readIORef outVar@@ -386,6 +395,21 @@             return unlisten         addCleanup_Listen unlistener l +-- | Take each list item and put it into a new transaction of its own.+--+-- An example use case of this might be a situation where we are splitting+-- a block of input data into frames. We obviously want each frame to have+-- its own transaction so that state is updated separately each frame.+split :: Event [a] -> Event a+split esa = Event gl cacheRef (dep esa)+  where+    cacheRef = unsafeNewIORef Nothing esa+    gl = do+        (l, push, nodeRef) <- ioReactive newEventImpl+        unlistener <- later $ linkedListen esa (Just nodeRef) False $ \as ->+            schedulePost $ map push as+        addCleanup_Listen unlistener l+ -- | Create a new 'Behavior' along with an action to push changes into it. -- American spelling. newBehavior :: a  -- ^ Initial behavior value@@ -502,7 +526,8 @@ data ReactiveState = ReactiveState {         asQueue1 :: Seq (Reactive ()),         asQueue2 :: PriorityQueue (Maybe (MVar Node)) (Reactive ()),-        asFinal  :: Seq (Reactive ())+        asFinal  :: Seq (Reactive ()),+        asPost   :: Seq (Reactive ())     }  instance Functor (R.Reactive Plain) where@@ -541,6 +566,9 @@ scheduleLast :: Reactive () -> Reactive () scheduleLast task = Reactive $ modify $ \as -> as { asFinal = asFinal as |> task } +schedulePost :: [Reactive ()] -> Reactive ()+schedulePost tasks = Reactive $ modify $ \as -> as { asPost = Seq.fromList tasks >< asPost as }+ data Listen a = Listen { runListen_ :: Maybe (MVar Node) -> Bool -> (a -> Reactive ()) -> Reactive (IO ()) }  -- | Unwrap an event's listener machinery.@@ -626,7 +654,7 @@         let listeners' = M.delete iD (noListeners no)         return $ listeners' `seq` no { noListeners = listeners' } -data Dep = Dep Any+newtype Dep = Dep Any  dep :: a -> Dep dep = Dep . unsafeCoerce