-- | -- Module : Simulation.Aivika.Experiment.ListSource -- Copyright : Copyright (c) 2013, David Sorokin -- License : BSD3 -- Maintainer : David Sorokin -- Stability : experimental -- Tested with: GHC 7.6.3 -- -- It represents an optimized source of data to construct the list. -- module Simulation.Aivika.Experiment.ListSource (ListSource, providerToDoubleListSource, providerToIntListSource, ListData, listSourceData, listDataList, ListRef, newListRef, addDataToListRef, readListRef) where import Data.IORef import Control.Monad import Simulation.Aivika.Event import Simulation.Aivika.Statistics import Simulation.Aivika.Experiment.Types -- | Represents the optimized source of data for constructing the list. data ListSource a = SingleValueSource (Event a) | MultipleValueSource (Event [a]) -- | Represents the optimized data by which the list will be created. data ListData a = SingleValueData !a | MultipleValueData [a] -- | Try to return the source of list data by the specified provider. providerToDoubleListSource :: SeriesProvider -> Maybe (ListSource Double) providerToDoubleListSource provider = case providerToDouble provider of Just x -> Just $ SingleValueSource x Nothing -> case providerToDoubleList provider of Just x -> Just $ MultipleValueSource x Nothing -> Nothing -- | Try to return the source of list data by the specified provider. providerToIntListSource :: SeriesProvider -> Maybe (ListSource Int) providerToIntListSource provider = case providerToInt provider of Just x -> Just $ SingleValueSource x Nothing -> case providerToIntList provider of Just x -> Just $ MultipleValueSource x Nothing -> Nothing -- | Get data from the source in the current time point. listSourceData :: ListSource a -> Event (ListData a) listSourceData (SingleValueSource x) = x >>= return . SingleValueData listSourceData (MultipleValueSource xs) = do ys <- xs zs <- forM ys $ \y -> return $ y `seq` y return $ MultipleValueData ys -- it contains strict data, which is important for big models -- | Return the list of values contained in the specified data. listDataList :: ListData a -> [a] listDataList (SingleValueData x) = [x] listDataList (MultipleValueData xs) = xs -- | Represents a reference to the list, optimized to work with the source of data. newtype ListRef a = ListRef { listRef :: IORef [ListData a] } -- | Create a new list reference. newListRef :: IO (ListRef a) newListRef = fmap ListRef $ newIORef [] -- | Add data to the list reference. addDataToListRef :: ListRef a -> ListData a -> IO () addDataToListRef (ListRef r) a = modifyIORef r (a :) -- | Read the list contained in the reference. readListRef :: ListRef a -> IO [a] readListRef (ListRef r) = do x <- readIORef r return $ concat $ map listDataList x