-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Framework for artificial life experiments. -- -- A software framework for automating experiments with artificial life. -- It provides a daemon which maintains its own clock, schedules -- events, provides logging, and ensures that each agent gets its turn to -- use the CPU. You can use other applications on the computer at the -- same time without fear of interfering with experiments; they will run -- normally, just more slowly. See the tutorial at -- https://github.com/mhwombat/creatur-examples/raw/master/Tutorial.pdf -- for examples on how to use the Créatúr framework. -- -- About the name: "Créatúr" (pronounced kray-toor) is an irish word -- meaning animal, creature, or an unfortunate person. @package creatur @version 5.6.2 -- | A simple rotating log, tailored to the needs of the Créatúr framework. module ALife.Creatur.Logger class Logger l writeToLog :: Logger l => String -> StateT l IO () timestamp :: IO String -- | TODO module ALife.Creatur.Genetics.Diploid -- | A diploid agent has two complete sets of genetic instructions. -- Instances of this class can be thought of as paired genes or paired -- instructions for building an agent. When two instructions in a pair -- differ, dominance relationships determine how the genes will be -- expressed in the agent. Minimal complete definition: -- express. class Diploid g where express x y = to $ gexpress (from x) (from y) express :: Diploid g => g -> g -> g expressMaybe :: Diploid g => Maybe g -> Maybe g -> Maybe g instance (Diploid a, Diploid b) => Diploid (a, b) instance Diploid a => Diploid (Maybe a) instance Diploid a => Diploid [a] instance Diploid Double instance Diploid Word64 instance Diploid Word32 instance Diploid Word16 instance Diploid Word8 instance Diploid Word instance Diploid Int instance Diploid Char instance Diploid Bool instance Diploid a => GDiploid (K1 i a) instance GDiploid a => GDiploid (M1 i c a) instance (GDiploid a, GDiploid b) => GDiploid (a :+: b) instance (GDiploid a, GDiploid b) => GDiploid (a :*: b) instance GDiploid U1 -- | ??? module ALife.Creatur.Genetics.Analysis class Analysable g where analyse = ganalyse . from analyse :: Analysable g => g -> String instance (Analysable a, Analysable b) => Analysable (Either a b) instance (Analysable a, Analysable b) => Analysable (a, b) instance Analysable a => Analysable (Maybe a) instance Analysable a => Analysable [a] instance Analysable Word16 instance Analysable Word8 instance Analysable Char instance Analysable Bool instance Analysable a => GAnalysable (K1 i a) instance GAnalysable a => GAnalysable (M1 i c a) instance (GAnalysable a, GAnalysable b) => GAnalysable (a :+: b) instance (GAnalysable a, GAnalysable b) => GAnalysable (a :*: b) instance GAnalysable U1 -- | Utility functions that don't fit anywhere else. module ALife.Creatur.Util -- | ilogBase n m returns the greatest integer not greater -- than the log base n of m. ilogBase :: (Integral a, Integral b, Integral c) => a -> b -> c -- | n isPowerOf m returns True if n is a -- power of m (i.e., if there exists an _integer_ k such that m^k = n) isPowerOf :: Integral a => a -> a -> Bool -- | isqrt n returns the greatest integer not greater than -- the square root of n. isqrt :: (Integral a, Integral b) => a -> b -- | perfectSquare n returns True if n is -- a perfect square (i.e., if there exists an _integer_ m such that m*m = -- n) perfectSquare :: Integral a => a -> Bool -- | Assuming xs is a sequence containing the elements of a matrix -- with k columns, cropRect (a,b) (c, d) k xs -- returns the elements of the submatrix from (a,b) in the upper -- left corner to (c,d) in the lower right corner). Note: Matrix -- indices begin at (0,0). -- -- Example: Suppose we have a 4x6 matrix and we want to -- extract the submatrix from (1,2) to (2,4), as illustrated below. -- --
-- a b c d e f -- g h i j k l ---> i j k -- m n o p q r o p q -- s t u v w x ---- -- We can represent the elements of the original matrix as -- ['a'..'x']. The elements of the submatrix are ['i', 'j', -- 'k', 'o', 'p', 'q'], or equivalently, "ijkopq". And that -- is what cropRect (1,2) (2,4) 6 ['a'..'x'] returns. cropRect :: (Int, Int) -> (Int, Int) -> [a] -> Int -> [a] -- | Assuming xs is a sequence containing the elements of a square -- matrix, cropSquare n xs returns the elements of the -- submatrix of size nxn, centred within the original -- matrix xs. -- -- Example: Suppose we have a 5x5 matrix and we want to -- extract the central 3x3 submatrix, as illustrated below. -- --
-- a b c d e -- f g h i j g h i -- k l m n o ---> l m n -- p q r s t q r s -- u v w x y ---- -- We can represent the elements of the original matrix as -- ['a'..'y']. The elements of the submatrix are ['g', 'h', -- 'i', 'l', 'm', 'n', 'q', 'r', 's'], or equivalently, -- "ghilmnqrs". And that is what cropSquare 3 -- ['a'..'y'] returns. cropSquare :: Int -> [a] -> [a] -- | replaceElement xs n x returns a copy of xs in -- which the nth element has been replaced with x. -- Causes an exception if xs has fewer than n+1 -- elements. Compare with safeReplaceElement. replaceElement :: [a] -> Int -> a -> [a] reverseLookup :: Eq b => b -> [(a, b)] -> Maybe a rotate :: [a] -> [a] -- | safeReplaceElement xs n x returns a copy of -- xs in which the nth element (if it exists) has been -- replaced with x. safeReplaceElement :: [a] -> Int -> a -> [a] -- | From http://www.haskell.org/haskellwiki/Random_shuffle shuffle :: RandomGen g => [a] -> Rand g [a] -- | Convert a list of bits to a string of 0s and 1s. boolsToBits :: [Bool] -> String -- | Show non-negative Integral numbers in binary. showBin :: (Integral a, Show a) => a -> ShowS stateMap :: Monad m => (s -> t) -> (t -> s) -> StateT s m a -> StateT t m a -- | The fromEither function takes a default value and an -- Either value. If the Either is Left, it returns -- the default value; otherwise, it returns the value contained in the -- Right. fromEither :: a -> Either e a -> a -- | Takes a list of Eithers and returns a list of all the -- Right values. catEithers :: [Either e a] -> [a] -- | Like modify, but the function that maps the old state to the new state -- operates in the inner monad. For example, -- --
-- s <- get -- s' = lift $ f s -- put s' ---- -- can be replaced with -- --
-- modifyLift f --modifyLift :: Monad m => (s -> m s) -> StateT s m () -- | Invoke a function in the inner monad, and pass the state as a -- parameter. Similar to modifyLift, but the function being invoked -- doesn't have a return value, so the state is not modified. For -- example, -- --
-- s <- get -- s' = lift $ f s ---- -- can be replaced with -- --
-- getLift f --getLift :: Monad m => (s -> m ()) -> StateT s m () -- | Utilities for working with genes that are encoded as a sequence of -- bits, using a Binary Reflected Gray Code (BRGC). -- -- A Gray code maps values to codes in a way that guarantees that the -- codes for two consecutive values will differ by only one bit. This -- feature can be useful in evolutionary programming because the genes -- resulting from a crossover operation are likely to be similar to the -- inputs. This helps to ensure that offspring are similar to their -- parents, as any radical changes from one generation to the next are -- the result of mutation alone. module ALife.Creatur.Genetics.BRGCBool -- | A class representing anything which is represented in, and determined -- by, an agent's genome. This might include traits, parameters, -- organs (components of agents), or even entire agents. Instances -- of this class can be thought of as genes, i.e., instructions for -- building an agent. class Genetic g where put = gput . from get = do { a <- gget; return $ fmap to a } getWithDefault d = fmap (fromEither d) get put :: Genetic g => g -> Writer () get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g type Sequence = [Bool] type Writer = StateT Sequence Identity write :: Genetic x => x -> Sequence runWriter :: Writer () -> Sequence type Reader = StateT (Sequence, Int) Identity read :: Genetic g => Sequence -> Either [String] g runReader :: Reader g -> Sequence -> g -- | Return the entire genome. copy :: Reader Sequence -- | Return the portion of the genome that has been read. consumed :: Reader Sequence type DiploidSequence = (Sequence, Sequence) type DiploidReader = StateT ((Sequence, Int), (Sequence, Int)) Identity readAndExpress :: (Genetic g, Diploid g) => DiploidSequence -> Either [String] g runDiploidReader :: DiploidReader g -> DiploidSequence -> g -- | Read the next pair of genes from twin sequences of genetic -- information, and return the resulting gene (after taking into account -- any dominance relationship) and the remaining (unread) portion of the -- two nucleotide strands. getAndExpress :: (Genetic g, Diploid g) => DiploidReader (Either [String] g) getAndExpressWithDefault :: (Genetic g, Diploid g) => g -> DiploidReader g -- | Return the entire genome. copy2 :: DiploidReader DiploidSequence -- | Return the portion of the genome that has been read. consumed2 :: DiploidReader DiploidSequence instance (Genetic a, Genetic b) => Genetic (Either a b) instance (Genetic a, Genetic b) => Genetic (a, b) instance Genetic a => Genetic (Maybe a) instance Genetic a => Genetic [a] instance Genetic Word16 instance Genetic Word8 instance Genetic Char instance Genetic Bool instance Genetic a => GGenetic (K1 i a) instance GGenetic a => GGenetic (M1 i c a) instance (GGenetic a, GGenetic b) => GGenetic (a :+: b) instance (GGenetic a, GGenetic b) => GGenetic (a :*: b) instance GGenetic U1 -- | Utilities for working with genes that are encoded as a sequence of -- bytes, using a Binary Reflected Gray Code (BRGC). -- -- A Gray code maps values to codes in a way that guarantees that the -- codes for two consecutive values will differ by only one bit. This -- feature can be useful in evolutionary programming because the genes -- resulting from a crossover operation are likely to be similar to the -- inputs. This helps to ensure that offspring are similar to their -- parents, as any radical changes from one generation to the next are -- the result of mutation alone. module ALife.Creatur.Genetics.BRGCWord8 -- | A class representing anything which is represented in, and determined -- by, an agent's genome. This might include traits, parameters, -- organs (components of agents), or even entire agents. Instances -- of this class can be thought of as genes, i.e., instructions for -- building an agent. class Genetic g where put = gput . from get = do { a <- gget; return $ fmap to a } getWithDefault d = fmap (fromEither d) get put :: Genetic g => g -> Writer () get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g type Sequence = [Word8] type Writer = StateT Sequence Identity write :: Genetic x => x -> Sequence runWriter :: Writer () -> Sequence type Reader = StateT (Sequence, Int) Identity read :: Genetic g => Sequence -> Either [String] g runReader :: Reader g -> Sequence -> g -- | Return the entire genome. copy :: Reader Sequence -- | Return the portion of the genome that has been read. consumed :: Reader Sequence type DiploidSequence = (Sequence, Sequence) type DiploidReader = StateT ((Sequence, Int), (Sequence, Int)) Identity readAndExpress :: (Genetic g, Diploid g) => DiploidSequence -> Either [String] g runDiploidReader :: DiploidReader g -> DiploidSequence -> g -- | Read the next pair of genes from twin sequences of genetic -- information, and return the resulting gene (after taking into account -- any dominance relationship) and the remaining (unread) portion of the -- two nucleotide strands. getAndExpress :: (Genetic g, Diploid g) => DiploidReader (Either [String] g) getAndExpressWithDefault :: (Genetic g, Diploid g) => g -> DiploidReader g -- | Return the entire genome. copy2 :: DiploidReader DiploidSequence -- | Return the portion of the genome that has been read. consumed2 :: DiploidReader DiploidSequence -- | Write a Word8 value to the genome without encoding it putRawWord8 :: Word8 -> Writer () -- | Read a Word8 value from the genome without decoding it getRawWord8 :: Reader (Either [String] Word8) -- | Write a raw sequence of Word8 values to the genome putRawWord8s :: [Word8] -> Writer () -- | Read a raw sequence of Word8 values from the genome getRawWord8s :: Int -> Reader (Either [String] [Word8]) instance (Genetic a, Genetic b) => Genetic (Either a b) instance (Genetic a, Genetic b) => Genetic (a, b) instance Genetic a => Genetic (Maybe a) instance Genetic a => Genetic [a] instance Genetic Word16 instance Genetic Word8 instance Genetic Char instance Genetic Bool instance Genetic a => GGenetic (K1 i a) instance GGenetic a => GGenetic (M1 i c a) instance (GGenetic a, GGenetic b) => GGenetic (a :+: b) instance (GGenetic a, GGenetic b) => GGenetic (a :*: b) instance GGenetic U1 -- | Utilities for working with genes that are encoded as a sequence of -- 16-bit words, using a Binary Reflected Gray Code (BRGC). -- -- A Gray code maps values to codes in a way that guarantees that the -- codes for two consecutive values will differ by only one bit. This -- feature can be useful in evolutionary programming because the genes -- resulting from a crossover operation are likely to be similar to the -- inputs. This helps to ensure that offspring are similar to their -- parents, as any radical changes from one generation to the next are -- the result of mutation alone. module ALife.Creatur.Genetics.BRGCWord16 -- | A class representing anything which is represented in, and determined -- by, an agent's genome. This might include traits, parameters, -- organs (components of agents), or even entire agents. Instances -- of this class can be thought of as genes, i.e., instructions for -- building an agent. class Genetic g where put = gput . from get = do { a <- gget; return $ fmap to a } getWithDefault d = fmap (fromEither d) get put :: Genetic g => g -> Writer () get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g type Sequence = [Word16] type Writer = StateT Sequence Identity write :: Genetic x => x -> Sequence runWriter :: Writer () -> Sequence type Reader = StateT (Sequence, Int) Identity read :: Genetic g => Sequence -> Either [String] g runReader :: Reader g -> Sequence -> g -- | Return the entire genome. copy :: Reader Sequence -- | Return the portion of the genome that has been read. consumed :: Reader Sequence type DiploidSequence = (Sequence, Sequence) type DiploidReader = StateT ((Sequence, Int), (Sequence, Int)) Identity readAndExpress :: (Genetic g, Diploid g) => DiploidSequence -> Either [String] g runDiploidReader :: DiploidReader g -> DiploidSequence -> g -- | Read the next pair of genes from twin sequences of genetic -- information, and return the resulting gene (after taking into account -- any dominance relationship) and the remaining (unread) portion of the -- two nucleotide strands. getAndExpress :: (Genetic g, Diploid g) => DiploidReader (Either [String] g) getAndExpressWithDefault :: (Genetic g, Diploid g) => g -> DiploidReader g -- | Return the entire genome. copy2 :: DiploidReader DiploidSequence -- | Return the portion of the genome that has been read. consumed2 :: DiploidReader DiploidSequence -- | Write a Word16 value to the genome without encoding it putRawWord16 :: Word16 -> Writer () -- | Read a Word16 value from the genome without decoding it getRawWord16 :: Reader (Either [String] Word16) -- | Write a raw sequence of Word16 values to the genome putRawWord16s :: [Word16] -> Writer () -- | Read a raw sequence of Word16 values from the genome getRawWord16s :: Int -> Reader (Either [String] [Word16]) instance (Genetic a, Genetic b) => Genetic (Either a b) instance (Genetic a, Genetic b) => Genetic (a, b) instance Genetic a => Genetic (Maybe a) instance Genetic a => Genetic [a] instance Genetic Word16 instance Genetic Word8 instance Genetic Char instance Genetic Bool instance Genetic a => GGenetic (K1 i a) instance GGenetic a => GGenetic (M1 i c a) instance (GGenetic a, GGenetic b) => GGenetic (a :+: b) instance (GGenetic a, GGenetic b) => GGenetic (a :*: b) instance GGenetic U1 -- | Provides a mechanism to break apart and rejoin sequences of data. -- Inspired by DNA recombination in biology, this technique can be used -- to recombine "genetic" instructions for building artificial life. module ALife.Creatur.Genetics.Recombination -- | Cuts two lists at the specified location, swaps the ends, and splices -- them. This is a variation of cutAndSplice where n == m. crossover :: Int -> ([a], [a]) -> ([a], [a]) -- | Cuts two lists at the specified locations, swaps the ends, and splices -- them. The resulting lists will be: a[0..n-1] ++ b[m..] b[0..m-1] -- ++ a[n..] Here are some examples. Expression -- Result cutAndSplice 2 5 ("abcdef", "ABCDEF") -- ("abF","ABCDEcdef") cutAndSplice 3 1 ("abcd", "ABCDEFG") -- ("abcBCDEFG","Ad") cutAndSplice 4 4 ("abcdef", "ABCDEF") -- ("abcdEF","ABCDef") If n <= 0 or m <= 0, the corresponding -- input list will be completely transferred to the other. -- Expression Result cutAndSplice 0 4 ("abcdef", -- "ABCDEF") ("EF","ABCDabcdef") cutAndSplice (-2) 4 ("abcd", -- "ABCDEFGH") ("EFGH","ABCDabcd") cutAndSplice 5 0 ("abcdef", -- "ABCDEF") ("abcdeABCDEF","f") If n or m are greater than or -- equal to length of the corresponding list, that list will not be -- transferred. Expression Result cutAndSplice -- 10 0 ("abcdef", "ABCDEF") ("abcdefABCDEF","") cutAndSplice 0 0 -- ("", "ABCDEF") ("ABCDEF","") cutAndSplice :: Int -> Int -> ([a], [a]) -> ([a], [a]) -- | Mutates a random element in the list. mutateList :: (Random n, RandomGen g) => [n] -> Rand g [n] -- | Mutates a random element in one list in a pair. mutatePairedLists :: (Random n, RandomGen g) => ([n], [n]) -> Rand g ([n], [n]) randomOneOfList :: RandomGen g => [a] -> Rand g a randomOneOfPair :: RandomGen g => (a, a) -> Rand g a -- | Same as crossover, except that the location is chosen -- at random. randomCrossover :: RandomGen g => ([a], [a]) -> Rand g ([a], [a]) -- | Same as cutAndSplice, except that the two locations -- are chosen at random. randomCutAndSplice :: RandomGen g => ([a], [a]) -> Rand g ([a], [a]) -- | Performs an operation a random number of times. The probability of -- repeating the operation n times is p^n. repeatWithProbability :: RandomGen g => Double -> (b -> Rand g b) -> b -> Rand g b -- | Performs an operation with the specified probability. withProbability :: RandomGen g => Double -> (b -> Rand g b) -> b -> Rand g b -- | A simple rotating log, tailored to the needs of the Créatúr framework. module ALife.Creatur.Logger.SimpleLogger -- | A rotating logger. data SimpleLogger -- | mkSimpleLogger f creates a logger that will write to -- file f. mkSimpleLogger :: FilePath -> SimpleLogger instance Show SimpleLogger instance Eq SimpleLogger instance Logger SimpleLogger -- | A simple rotating log, tailored to the needs of the Créatúr framework. module ALife.Creatur.Logger.SimpleRotatingLogger class Logger l writeToLog :: Logger l => String -> StateT l IO () -- | A rotating logger. data SimpleRotatingLogger -- | mkSimpleRotatingLogger d prefix n creates a logger -- that will write to directory d. The log "rotates" (starts a -- new log file) every n records. Log files follow the naming -- convention prefix.k, where k is the number of -- the last log record contained in the file. If logging has already been -- set up in directory, then logging will continue where it left -- off; appending to the most recent log file. mkSimpleRotatingLogger :: FilePath -> String -> Int -> SimpleRotatingLogger instance Show SimpleRotatingLogger instance Eq SimpleRotatingLogger instance Logger SimpleRotatingLogger -- | Provides a UNIX daemon to run an experiment using the Créatúr -- framework. module ALife.Creatur.Daemon -- | Daemon configuration. If username is null, the daemon will -- run under the login name. data Daemon s Daemon :: (s -> IO s) -> (s -> IO ()) -> (s -> SomeException -> IO (Bool, s)) -> StateT s IO Bool -> String -> Int -> Daemon s onStartup :: Daemon s -> s -> IO s onShutdown :: Daemon s -> s -> IO () onException :: Daemon s -> s -> SomeException -> IO (Bool, s) -- | The agent task. task :: Daemon s -> StateT s IO Bool username :: Daemon s -> String -- | Number of microseconds to sleep between agent tasks. sleepTime :: Daemon s -> Int -- | launch daemon state creates a daemon running under the -- current user's real userID, which invokes task. launch :: Daemon s -> s -> IO () -- | A state which persists between runs. module ALife.Creatur.Persistent data Persistent a -- | Creates a counter that will store its value in the specified file. mkPersistent :: a -> FilePath -> Persistent a getPS :: Read a => StateT (Persistent a) IO a putPS :: (Show a, Read a) => a -> StateT (Persistent a) IO () instance Show a => Show (Persistent a) instance Eq a => Eq (Persistent a) -- | An exhaustible resource which persists between runs. module ALife.Creatur.EnergyPool class EnergyPool e replenish :: EnergyPool e => Double -> StateT e IO () withdraw :: EnergyPool e => Double -> StateT e IO Double available :: EnergyPool e => StateT e IO Double type PersistentEnergyPool = Persistent Double -- | Creates a resource that will store its value in the specified file. mkPersistentEnergyPool :: FilePath -> PersistentEnergyPool instance EnergyPool PersistentEnergyPool -- | A simple task list which persists between runs. module ALife.Creatur.Checklist class Checklist t status :: Checklist t => StateT t IO Status markDone :: Checklist t => String -> StateT t IO () notStarted :: Checklist t => StateT t IO Bool done :: Checklist t => StateT t IO Bool setItems :: Checklist t => [String] -> StateT t IO () delete :: Checklist t => String -> StateT t IO () type PersistentChecklist = Persistent Status -- | Creates a counter that will store its value in the specified file. mkPersistentChecklist :: FilePath -> PersistentChecklist instance Checklist PersistentChecklist -- | Database interface for the Créatúr framework. module ALife.Creatur.Database -- | A database offering storage and retrieval for records. class Database d where type family DBRecord d keys :: Database d => StateT d IO [String] numRecords :: Database d => StateT d IO Int archivedKeys :: Database d => StateT d IO [String] lookup :: (Database d, Serialize (DBRecord d)) => String -> StateT d IO (Either String (DBRecord d)) lookupInArchive :: (Database d, Serialize (DBRecord d)) => String -> StateT d IO (Either String (DBRecord d)) store :: (Database d, Record (DBRecord d), Serialize (DBRecord d)) => DBRecord d -> StateT d IO () delete :: (Database d, Serialize (DBRecord d)) => String -> StateT d IO () class Record r key :: Record r => r -> String class Record r => SizedRecord r size :: SizedRecord r => r -> Int -- | A ridiculously simple database that stores each record in a separate -- file. The name of the file is the record's key. module ALife.Creatur.Database.FileSystem -- | A simple database where each record is stored in a separate file, and -- the name of the file is the record's key. data FSDatabase r -- | mkFSDatabase d (re)creates the FSDatabase in the -- directory d. mkFSDatabase :: FilePath -> FSDatabase r instance Show (FSDatabase r) instance Eq (FSDatabase r) instance Database (FSDatabase r) -- | A module containing private CachedFileSystem internals. Most -- developers should use CachedFileSystem instead. This module is subject -- to change without notice. module ALife.Creatur.Database.CachedFileSystemInternal -- | A simple database where each record is stored in a separate file, and -- the name of the file is the record's key. data CachedFSDatabase r CachedFSDatabase :: FSDatabase r -> [r] -> Int -> CachedFSDatabase r database :: CachedFSDatabase r -> FSDatabase r cache :: CachedFSDatabase r -> [r] maxCacheSize :: CachedFSDatabase r -> Int withFSDB :: Monad m => StateT (FSDatabase r) m a -> StateT (CachedFSDatabase r) m a fromCache :: Record r => String -> StateT (CachedFSDatabase r) IO (Maybe r) addToCache :: SizedRecord r => r -> StateT (CachedFSDatabase r) IO () deleteByKeyFromCache :: SizedRecord r => String -> StateT (CachedFSDatabase r) IO () deleteFromCache :: SizedRecord r => r -> StateT (CachedFSDatabase r) IO () trimCache :: SizedRecord r => StateT (CachedFSDatabase r) IO () trim :: SizedRecord r => Int -> [r] -> [r] listSize :: SizedRecord r => [r] -> Int -- | mkFSDatabase d (re)creates the FSDatabase in the -- directory d. mkCachedFSDatabase :: FilePath -> Int -> CachedFSDatabase r instance Show r => Show (CachedFSDatabase r) instance Eq r => Eq (CachedFSDatabase r) instance SizedRecord r => Database (CachedFSDatabase r) -- | A database that stores each record in a separate file and maintains a -- cache of recently-accessed records. The name of the file is the -- record's key. module ALife.Creatur.Database.CachedFileSystem -- | A simple database where each record is stored in a separate file, and -- the name of the file is the record's key. data CachedFSDatabase r -- | mkFSDatabase d (re)creates the FSDatabase in the -- directory d. mkCachedFSDatabase :: FilePath -> Int -> CachedFSDatabase r -- | Definitions used throughout the Créatúr framework. module ALife.Creatur -- | An artificial life species. All species used in Créatúr must be an -- instance of this class. class Record a => Agent a where agentId = key agentId :: Agent a => a -> AgentId isAlive :: Agent a => a -> Bool -- | A unique ID associated with an agent. type AgentId = String -- | The internal clock used by Créatúr is a simple counter. type Time = Int programVersion :: String -- | An internal simulation clock which persists between runs. This is a -- simple counter, completely independent from any system clock or -- hardware clock. The clock does not automatically advance, it only -- advances when incTime is called. In this way, the -- Créatúr framework will run consistently, treating all agents fairly, -- regardless of current processor load. It also ensures that data -- obtained from simulation runs on different machines with different CPU -- performance can still be meaningfully compared. module ALife.Creatur.Clock -- | A clock representing the time in a Créatúr universe. It is used to -- schedule events and ensure that each agent gets its fair share of the -- CPU. This clock is entirely separate from the system clock. It -- advances only when incTime is called. This allows -- Créatúr to run without being affected by other processes which might -- be using the CPU at the same time. class Clock c currentTime :: Clock c => StateT c IO Time incTime :: Clock c => StateT c IO () -- | A simple counter which persists between runs. module ALife.Creatur.Counter class Counter c current :: Counter c => StateT c IO Int increment :: Counter c => StateT c IO () type PersistentCounter = Persistent Int -- | Creates a counter that will store its value in the specified file. mkPersistentCounter :: FilePath -> PersistentCounter instance Clock PersistentCounter instance Counter PersistentCounter -- | Assigns a unique ID upon request. IDs generated by an Namer -- are guaranteed to be unique within a given universe, across all -- simulation runs. module ALife.Creatur.Namer class Namer n genName :: Namer n => StateT n IO String data SimpleNamer mkSimpleNamer :: String -> FilePath -> SimpleNamer instance Show SimpleNamer instance Eq SimpleNamer instance Namer SimpleNamer -- | A reproduction method for artificial lifeforms where: -- --