GPLV3.0 or later copyright brmlab.cz contact timothyhobbs@seznam.cz Copyright 2012. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . This module is KNOWN to be buggy :/ >module Control.Concurrent.StateRecords where >import Control.Concurrent.ThreadObject >import Control.Exception >data RecorderSignal signal = RecorderSignal Bool (Maybe signal) >type History a = (Maybe a, [a],[a]) This isn't a very good type name. This is one instance of a set of previous values that a threadObject as had. >type Record a signal = (History a,(ThreadObject a signal)) >type StateRecords a signal = ThreadObject (Record a signal) () >stateRecords :: Exception exception => ThreadObject a signal -> (Record a signal -> exception -> IO (Record a signal)) -> IO (StateRecords a signal) >stateRecords to exceptionHandler = do > stateRecordsObject <- threadObject > objectInit stateRecordsObject (DoNotSync (SeedInitially ((Nothing,[],[]),to))) noSyncOnPut exceptionHandler > return stateRecordsObject >recordState :: Int -> StateRecords a signal -> a -> IO () >recordState n stateRecordsObject value = do > updateIO stateRecordsObject > (\((lastStateMaybe,stack1,stack2),to)-> do print "length" print $ length stack1 print "n" print n > if length stack1 >= n > then case lastStateMaybe of > Just lastState -> do print 1 > return ((Just value,lastState:[],stack1), to) > Nothing -> do print 2 > return ((Just value,[],stack1), to) > else case lastStateMaybe of > Just lastState -> do print 3; > return ((Just value,lastState:stack1,stack2), to) > Nothing -> do print 4; > return ((Just value,stack1,stack2), to)) | This is to undo an action applied the thread object which is used as your "metronome", that thread object, within who's syncOnPut, are the recordState commands. >undoStateActionOfRecorder :: StateRecords a (RecorderSignal signal) -> IO Bool >undoStateActionOfRecorder stateRecordsObject = do > undoStateAction' stateRecordsObject (\to value -> updateWithSignal to (\_->value) (RecorderSignal False Nothing)) >undoStateAction :: StateRecords a signal -> IO Bool >undoStateAction stateRecordsObject = do > undoStateAction' stateRecordsObject (\to value -> update to (\_->value)) >undoStateAction' :: StateRecords a signal -> (ThreadObject a signal -> a -> IO ()) -> IO Bool >undoStateAction' stateRecordsObject myUpdate = do > updateIOReturning stateRecordsObject > (\(stacks,to)-> do > case stacks of > (Just _,value:stack1,stack2) -> do > myUpdate to value print "Jv" > return (((Nothing,stack1,stack2),to),True) > (Nothing,value:stack1,stack2) -> do > myUpdate to value print "Nv" > return (((Nothing,stack1,stack2),to),True) > (Just _,[],value:stack2) -> do > myUpdate to value print "J[]" > return (((Nothing,stack2,[]),to),True) > (Nothing,[],value:stack2) -> do > myUpdate to value print "N[]" > return (((Nothing,stack2,[]),to),True) > (Just _,[],[]) -> do print "J[]" > return (((Nothing,[],[]),to),False) > (Nothing,[],[]) -> do print "N[]" > return (((Nothing,[],[]),to),False))