úÎ9Ø8J     None>A thin wrapper around STM. The main feature is the ability to   ! updates of the underlying data. =An opaque type wrapping any kind of user data for use in the  monad. $The type family at the heart of TX. HYou make any data type you want to use with the TX monad an instance of   and define & constructors for each of the methods N acting on this type that you want to be able to record during a transaction.  Then you implement + in such a way that for each of the Update 0 constructors, the appropiate method is called.  Example:  - data MyDB = MyDB { posts :: TVar [String] }  ! instance Persistable MyDB where * data Update MyDB = CreatePost String . | ModifyPost Int String  3 replay (CreatePost p) = void $ createPost p . replay (ModifyPost n p) = modifyPost n p where  createPost and  modifyPost are functions in the TX monad:  % createPost :: String -> TX MyDB Int  createPost p = do  record (CreatePost p)  (MyDB posts) <- getData  liftSTM $ do  ps <- readTVar posts % writeTVar posts (ps ++ [p])  return $ length ps  + modifyPost :: Int -> String -> TX MyDB ()  modifyPost n p = do  record (ModifyPost n p)  (MyDB posts) <- getData  liftSTM $ do  ps <- readTVar posts $ let (xs,ys) = splitAt n ps + ps' = xs ++ p : (tail ys)  writeTVar posts ps'  Note that Update! also needs to be an instance of  . Currently,  it'As not possible to derive SafeCopy instances for associated types . automatically, so you have to do it by hand: ' instance SafeCopy (Update MyDB) where B putCopy (CreatePost p) = contain $ putWord8 0 >> safePut p O putCopy (ModifyPost n p) = contain $ putWord8 1 >> safePut n >> safePut p  getCopy = contain $ do  tag <- getWord8  case tag of ) 0 -> CreatePost <$> safeGet 5 1 -> ModifyPost <$> safeGet <*> safeGet 5 _ -> fail $ "unknown tag: " ++ show tag ;Opens the database at the given path or creates a new one. GClose a database. Blocks until all pending recordings been serialized. 8 Using a database after it has been closed is an error. mapDecode f nextChunk repeatedly calls  nextChunk to get a  (, (partially) decodes this string using  and  and then applies f- to the (final) result. This continues until   nextChunk returns an empty ByteString. EOperate non-persistently on the user data contained in the database. -Perform a series of TX actions persistently. ONote that there is no guarantee that all recorded updates have been serialized O when the functions returns. As such, durability is only partially guaranteed. Since this calls  on the underlying STM actions, % the same caveats apply (e.g. you can't use it inside unsafePerformIO).  Record an 8 to be serialized to disk when the transaction commits. E If the transaction retries, the update is still only recorded once. ? If the transaction aborts, the update is not recorded at all. %Get the user data from the database. Run STM actions inside TX. <Throw an exception in TX, which will abort the transaction. throwTX = liftSTM . throwSTM 8Unsafely performs IO in the TX monad. Highly dangerous!  The same caveats as with  apply. &unsafeIOToTX = liftSTM . unsafeIOToSTM act <?># err = maybe (throwTX err) return =<< actLocation of the log file. 8Base data. Any existing log is replayed on top of this.           !"# tx-0.1.0.0TXDatabase PersistableUpdatereplay openDatabase closeDatabase withUserData persistentlyrecordgetDataliftSTMthrowTX unsafeIOToTXsafecopy-0.8.2Data.SafeCopy.SafeCopySafeCopy mapDecodebytestring-0.10.0.2Data.ByteString.Internal ByteStringsafeGetbase GHC.Conc.Sync atomically unsafeIOToSTMuserData logHandlelogQueue_record serializerTid replayUpdates serializer