-- 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.9.12 -- | A simple rotating log, tailored to the needs of the Créatúr framework. module ALife.Creatur.Logger class Logger l -- | writeToLog msg formats and writes a new log message. 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) -- | Given two possible forms of a gene, express takes into -- account any dominance relationship, and returns a gene representing -- the result. express :: Diploid g => g -> g -> g expressMaybe :: Diploid g => Maybe g -> Maybe g -> Maybe g instance ALife.Creatur.Genetics.Diploid.GDiploid GHC.Generics.U1 instance (ALife.Creatur.Genetics.Diploid.GDiploid a, ALife.Creatur.Genetics.Diploid.GDiploid b) => ALife.Creatur.Genetics.Diploid.GDiploid (a GHC.Generics.:*: b) instance (ALife.Creatur.Genetics.Diploid.GDiploid a, ALife.Creatur.Genetics.Diploid.GDiploid b) => ALife.Creatur.Genetics.Diploid.GDiploid (a GHC.Generics.:+: b) instance ALife.Creatur.Genetics.Diploid.GDiploid a => ALife.Creatur.Genetics.Diploid.GDiploid (GHC.Generics.M1 i c a) instance ALife.Creatur.Genetics.Diploid.Diploid a => ALife.Creatur.Genetics.Diploid.GDiploid (GHC.Generics.K1 i a) instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Types.Bool instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Types.Char instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Types.Int instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Types.Word instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Word.Word8 instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Word.Word16 instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Word.Word32 instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Word.Word64 instance ALife.Creatur.Genetics.Diploid.Diploid GHC.Types.Double instance ALife.Creatur.Genetics.Diploid.Diploid a => ALife.Creatur.Genetics.Diploid.Diploid [a] instance ALife.Creatur.Genetics.Diploid.Diploid a => ALife.Creatur.Genetics.Diploid.Diploid (GHC.Base.Maybe a) instance (ALife.Creatur.Genetics.Diploid.Diploid a, ALife.Creatur.Genetics.Diploid.Diploid b) => ALife.Creatur.Genetics.Diploid.Diploid (a, b) -- | ??? module ALife.Creatur.Genetics.Analysis class Analysable g where analyse = ganalyse . from -- | Analyses a genetic sequence. analyse :: Analysable g => g -> String instance ALife.Creatur.Genetics.Analysis.GAnalysable GHC.Generics.U1 instance (ALife.Creatur.Genetics.Analysis.GAnalysable a, ALife.Creatur.Genetics.Analysis.GAnalysable b) => ALife.Creatur.Genetics.Analysis.GAnalysable (a GHC.Generics.:*: b) instance (ALife.Creatur.Genetics.Analysis.GAnalysable a, ALife.Creatur.Genetics.Analysis.GAnalysable b) => ALife.Creatur.Genetics.Analysis.GAnalysable (a GHC.Generics.:+: b) instance ALife.Creatur.Genetics.Analysis.GAnalysable a => ALife.Creatur.Genetics.Analysis.GAnalysable (GHC.Generics.M1 i c a) instance ALife.Creatur.Genetics.Analysis.Analysable a => ALife.Creatur.Genetics.Analysis.GAnalysable (GHC.Generics.K1 i a) instance ALife.Creatur.Genetics.Analysis.Analysable GHC.Types.Bool instance ALife.Creatur.Genetics.Analysis.Analysable GHC.Types.Char instance ALife.Creatur.Genetics.Analysis.Analysable GHC.Word.Word8 instance ALife.Creatur.Genetics.Analysis.Analysable GHC.Word.Word16 instance ALife.Creatur.Genetics.Analysis.Analysable a => ALife.Creatur.Genetics.Analysis.Analysable [a] instance ALife.Creatur.Genetics.Analysis.Analysable a => ALife.Creatur.Genetics.Analysis.Analysable (GHC.Base.Maybe a) instance (ALife.Creatur.Genetics.Analysis.Analysable a, ALife.Creatur.Genetics.Analysis.Analysable b) => ALife.Creatur.Genetics.Analysis.Analysable (a, b) instance (ALife.Creatur.Genetics.Analysis.Analysable a, ALife.Creatur.Genetics.Analysis.Analysable b) => ALife.Creatur.Genetics.Analysis.Analysable (Data.Either.Either a b) -- | 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 getWithName s = do { g0 <- get; return $ case g0 of { (Left xs) -> Left ((s ++ ":") : xs) (Right g1) -> Right g1 } } -- | Writes a gene to a sequence. put :: Genetic g => g -> Writer () -- | Reads the next gene in a sequence. get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g getWithName :: Genetic g => String -> Reader (Either [String] 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 ALife.Creatur.Genetics.BRGCBool.GGenetic GHC.Generics.U1 instance (ALife.Creatur.Genetics.BRGCBool.GGenetic a, ALife.Creatur.Genetics.BRGCBool.GGenetic b) => ALife.Creatur.Genetics.BRGCBool.GGenetic (a GHC.Generics.:*: b) instance (ALife.Creatur.Genetics.BRGCBool.GGenetic a, ALife.Creatur.Genetics.BRGCBool.GGenetic b) => ALife.Creatur.Genetics.BRGCBool.GGenetic (a GHC.Generics.:+: b) instance ALife.Creatur.Genetics.BRGCBool.GGenetic a => ALife.Creatur.Genetics.BRGCBool.GGenetic (GHC.Generics.M1 i c a) instance ALife.Creatur.Genetics.BRGCBool.Genetic a => ALife.Creatur.Genetics.BRGCBool.GGenetic (GHC.Generics.K1 i a) instance ALife.Creatur.Genetics.BRGCBool.Genetic GHC.Types.Bool instance ALife.Creatur.Genetics.BRGCBool.Genetic GHC.Types.Char instance ALife.Creatur.Genetics.BRGCBool.Genetic GHC.Word.Word8 instance ALife.Creatur.Genetics.BRGCBool.Genetic GHC.Word.Word16 instance ALife.Creatur.Genetics.BRGCBool.Genetic a => ALife.Creatur.Genetics.BRGCBool.Genetic [a] instance ALife.Creatur.Genetics.BRGCBool.Genetic a => ALife.Creatur.Genetics.BRGCBool.Genetic (GHC.Base.Maybe a) instance (ALife.Creatur.Genetics.BRGCBool.Genetic a, ALife.Creatur.Genetics.BRGCBool.Genetic b) => ALife.Creatur.Genetics.BRGCBool.Genetic (a, b) instance (ALife.Creatur.Genetics.BRGCBool.Genetic a, ALife.Creatur.Genetics.BRGCBool.Genetic b) => ALife.Creatur.Genetics.BRGCBool.Genetic (Data.Either.Either a b) -- | 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 -- | Writes a gene to a sequence. put :: Genetic g => g -> Writer () -- | Reads the next gene in a sequence. get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g type Sequence = [Word8] type Writer = StateT (Sequence, [String]) Identity write :: Genetic x => x -> Sequence runWriter :: Writer () -> (Sequence, [String]) type Reader = StateT (Sequence, Int, [String]) Identity read :: Genetic g => Sequence -> Either [String] g runReader :: Reader (Either [String] g) -> Sequence -> (Either [String] g, [String]) -- | 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, [String]), (Sequence, Int, [String])) 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 putAndReport :: [Word8] -> String -> Writer () getAndReport :: Int -> ([Word8] -> (Either String (g, String))) -> Reader (Either [String] g) -- | 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 ALife.Creatur.Genetics.BRGCWord8.GGenetic GHC.Generics.U1 instance (ALife.Creatur.Genetics.BRGCWord8.GGenetic a, ALife.Creatur.Genetics.BRGCWord8.GGenetic b) => ALife.Creatur.Genetics.BRGCWord8.GGenetic (a GHC.Generics.:*: b) instance (ALife.Creatur.Genetics.BRGCWord8.GGenetic a, ALife.Creatur.Genetics.BRGCWord8.GGenetic b) => ALife.Creatur.Genetics.BRGCWord8.GGenetic (a GHC.Generics.:+: b) instance ALife.Creatur.Genetics.BRGCWord8.GGenetic a => ALife.Creatur.Genetics.BRGCWord8.GGenetic (GHC.Generics.M1 i c a) instance ALife.Creatur.Genetics.BRGCWord8.Genetic a => ALife.Creatur.Genetics.BRGCWord8.GGenetic (GHC.Generics.K1 i a) instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Types.Bool instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Types.Char instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Word.Word8 instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Word.Word16 instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Word.Word32 instance ALife.Creatur.Genetics.BRGCWord8.Genetic GHC.Word.Word64 instance ALife.Creatur.Genetics.BRGCWord8.Genetic a => ALife.Creatur.Genetics.BRGCWord8.Genetic [a] instance ALife.Creatur.Genetics.BRGCWord8.Genetic a => ALife.Creatur.Genetics.BRGCWord8.Genetic (GHC.Base.Maybe a) instance (ALife.Creatur.Genetics.BRGCWord8.Genetic a, ALife.Creatur.Genetics.BRGCWord8.Genetic b) => ALife.Creatur.Genetics.BRGCWord8.Genetic (a, b) instance (ALife.Creatur.Genetics.BRGCWord8.Genetic a, ALife.Creatur.Genetics.BRGCWord8.Genetic b) => ALife.Creatur.Genetics.BRGCWord8.Genetic (Data.Either.Either a b) -- | 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 getWithName s = do { g0 <- get; return $ case g0 of { (Left xs) -> Left ((s ++ ":") : xs) (Right g1) -> Right g1 } } -- | Writes a gene to a sequence. put :: Genetic g => g -> Writer () -- | Reads the next gene in a sequence. get :: Genetic g => Reader (Either [String] g) getWithDefault :: Genetic g => g -> Reader g getWithName :: Genetic g => String -> Reader (Either [String] 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 ALife.Creatur.Genetics.BRGCWord16.GGenetic GHC.Generics.U1 instance (ALife.Creatur.Genetics.BRGCWord16.GGenetic a, ALife.Creatur.Genetics.BRGCWord16.GGenetic b) => ALife.Creatur.Genetics.BRGCWord16.GGenetic (a GHC.Generics.:*: b) instance (ALife.Creatur.Genetics.BRGCWord16.GGenetic a, ALife.Creatur.Genetics.BRGCWord16.GGenetic b) => ALife.Creatur.Genetics.BRGCWord16.GGenetic (a GHC.Generics.:+: b) instance ALife.Creatur.Genetics.BRGCWord16.GGenetic a => ALife.Creatur.Genetics.BRGCWord16.GGenetic (GHC.Generics.M1 i c a) instance ALife.Creatur.Genetics.BRGCWord16.Genetic a => ALife.Creatur.Genetics.BRGCWord16.GGenetic (GHC.Generics.K1 i a) instance ALife.Creatur.Genetics.BRGCWord16.Genetic GHC.Types.Bool instance ALife.Creatur.Genetics.BRGCWord16.Genetic GHC.Types.Char instance ALife.Creatur.Genetics.BRGCWord16.Genetic GHC.Word.Word8 instance ALife.Creatur.Genetics.BRGCWord16.Genetic GHC.Word.Word16 instance ALife.Creatur.Genetics.BRGCWord16.Genetic a => ALife.Creatur.Genetics.BRGCWord16.Genetic [a] instance ALife.Creatur.Genetics.BRGCWord16.Genetic a => ALife.Creatur.Genetics.BRGCWord16.Genetic (GHC.Base.Maybe a) instance (ALife.Creatur.Genetics.BRGCWord16.Genetic a, ALife.Creatur.Genetics.BRGCWord16.Genetic b) => ALife.Creatur.Genetics.BRGCWord16.Genetic (a, b) instance (ALife.Creatur.Genetics.BRGCWord16.Genetic a, ALife.Creatur.Genetics.BRGCWord16.Genetic b) => ALife.Creatur.Genetics.BRGCWord16.Genetic (Data.Either.Either a b) -- | 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 GHC.Classes.Eq ALife.Creatur.Logger.SimpleLogger.SimpleLogger instance GHC.Show.Show ALife.Creatur.Logger.SimpleLogger.SimpleLogger instance ALife.Creatur.Logger.Logger ALife.Creatur.Logger.SimpleLogger.SimpleLogger -- | A simple rotating log, tailored to the needs of the Créatúr framework. module ALife.Creatur.Logger.SimpleRotatingLogger class Logger l -- | writeToLog msg formats and writes a new log message. 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 GHC.Classes.Eq ALife.Creatur.Logger.SimpleRotatingLogger.SimpleRotatingLogger instance GHC.Show.Show ALife.Creatur.Logger.SimpleRotatingLogger.SimpleRotatingLogger instance ALife.Creatur.Logger.Logger ALife.Creatur.Logger.SimpleRotatingLogger.SimpleRotatingLogger -- | Provides a UNIX daemon to run an experiment using the Créatúr -- framework. module ALife.Creatur.Daemon -- | The work to be performed by a daemon. data Job s Job :: (s -> IO s) -> (s -> IO ()) -> (s -> SomeException -> IO s) -> StateT s IO () -> Int -> Job s -- | Operations to perform on startup. [onStartup] :: Job s -> s -> IO s -- | Operations to perform on shutdown. [onShutdown] :: Job s -> s -> IO () -- | Operations to perform if an exception occurs. [onException] :: Job s -> s -> SomeException -> IO s -- | Operations to perform repeatedly while running. [task] :: Job s -> StateT s IO () -- | Number of microseconds to sleep between invocations of -- task. [sleepTime] :: Job s -> Int data CreaturDaemon p s CreaturDaemon :: CreateDaemon p -> Job s -> CreaturDaemon p s [daemon] :: CreaturDaemon p s -> CreateDaemon p [job] :: CreaturDaemon p s -> Job s -- | Creates a simple daemon to run a job. The daemon will run under the -- login name. simpleDaemon :: Job s -> s -> CreateDaemon () -- | launch daemon state creates a daemon, which invokes -- daemon. *Note:* If user (in -- daemon) is Just "", the daemon will run under -- the login name. If user is Nothing, the daemon will -- run under the name of the executable file containing the daemon. launch :: CreaturDaemon p s -> IO () launchInteractive :: Job s -> s -> IO () requestShutdown :: 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 () modifyPS :: (Show a, Read a) => (a -> a) -> StateT (Persistent a) IO () runPS :: Read a => (a -> b) -> StateT (Persistent a) IO b instance GHC.Classes.Eq a => GHC.Classes.Eq (ALife.Creatur.Persistent.Persistent a) instance GHC.Read.Read a => GHC.Read.Read (ALife.Creatur.Persistent.Persistent a) instance GHC.Show.Show a => GHC.Show.Show (ALife.Creatur.Persistent.Persistent a) -- | 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 ALife.Creatur.Checklist.Checklist ALife.Creatur.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 -- | Get a list of all active keys in the database. keys :: Database d => StateT d IO [String] -- | Return the number of records stored in the database. numRecords :: Database d => StateT d IO Int -- | Get a list of all archived keys in the database. If the database does -- not implement archiving, it may return an empty list. archivedKeys :: Database d => StateT d IO [String] -- | Read an active record from the database. lookup :: (Database d, Serialize (DBRecord d)) => String -> StateT d IO (Either String (DBRecord d)) -- | Read an archived record from the database. lookupInArchive :: (Database d, Serialize (DBRecord d)) => String -> StateT d IO (Either String (DBRecord d)) -- | Write a record to the database. If an agent with the same name already -- exists, it will be overwritten. store :: (Database d, Record (DBRecord d), Serialize (DBRecord d)) => DBRecord d -> StateT d IO () -- | Remove a record from the database. The database may archive records -- rather than simply deleting them. 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 GHC.Classes.Eq (ALife.Creatur.Database.FileSystem.FSDatabase r) instance GHC.Show.Show (ALife.Creatur.Database.FileSystem.FSDatabase r) instance ALife.Creatur.Database.Database (ALife.Creatur.Database.FileSystem.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 GHC.Classes.Eq r => GHC.Classes.Eq (ALife.Creatur.Database.CachedFileSystemInternal.CachedFSDatabase r) instance GHC.Show.Show r => GHC.Show.Show (ALife.Creatur.Database.CachedFileSystemInternal.CachedFSDatabase r) instance ALife.Creatur.Database.SizedRecord r => ALife.Creatur.Database.Database (ALife.Creatur.Database.CachedFileSystemInternal.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 -- | Returns the agent ID. agentId :: Agent a => a -> AgentId -- | Returns True if the agent is alive, false otherwise. 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 -- | The current time, measured in "ticks" currentTime :: Clock c => StateT c IO Time -- | Advance the clock to the next "tick". 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 ALife.Creatur.Counter.Counter ALife.Creatur.Counter.PersistentCounter instance ALife.Creatur.Clock.Clock ALife.Creatur.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 -- | Assign a unique ID using the supplied prefix. genName :: Namer n => StateT n IO String data SimpleNamer mkSimpleNamer :: String -> FilePath -> SimpleNamer instance GHC.Classes.Eq ALife.Creatur.Namer.SimpleNamer instance GHC.Show.Show ALife.Creatur.Namer.SimpleNamer instance ALife.Creatur.Namer.Namer ALife.Creatur.Namer.SimpleNamer -- | A reproduction method for artificial lifeforms where: -- -- module ALife.Creatur.Genetics.Reproduction.Sexual -- | A species that reproduces, transmitting genetic information to its -- offspring. Minimal complete definition: all except mate. class Reproductive a where type family Strand a makeOffspring a b name = do { ga <- produceGamete a; gb <- produceGamete b; return $ build name (ga, gb) } -- | From the two strands of the genetic information from this -- agent, creates a single strand that will contribute to the -- child's genome. (This is analogous to creating either a single sperm -- or ova.) produceGamete :: (Reproductive a, RandomGen r) => a -> Rand r (Strand a) -- | Builds an agent based on the genome provided, if it is possible to do -- so. build :: Reproductive a => AgentId -> (Strand a, Strand a) -> Either [String] a -- | makeOffspring (parent1, parent2) name uses the genetic -- information from parent1 and parent2 to produce a -- child with the agent ID name. The default implementation: -- --
    --
  1. Calls produceGamete to produce a single strand of -- genetic information from each parent.
  2. --
  3. Pairs the two strands to create a genome for the child.
  4. --
  5. Calls build construct a child with this -- genome.
  6. --
makeOffspring :: (Reproductive a, RandomGen r) => a -> a -> AgentId -> Rand r (Either [String] a) -- | A reproduction method for artificial lifeforms where: -- -- module ALife.Creatur.Genetics.Reproduction.SimplifiedSexual -- | A species that reproduces, transmitting genetic information to its -- offspring. Minimal complete definition: all except mate. class Reproductive a where type family Strand a makeOffspring a b name = do { g <- recombine a b; return $ build name g } -- | Recombines the genetic information from two parents, creating genetic -- information for potential offspring. -- -- Typically this involves the following steps: -- --
    --
  1. Recombine the two strands of genetic information (one from each -- parent) to obtain two new strands.
  2. --
  3. Discard one strand, and return the remaining one.
  4. --
recombine :: (Reproductive a, RandomGen r) => a -> a -> Rand r (Strand a) -- | Builds an agent based on the genome provided, if it is possible to do -- so. build :: Reproductive a => AgentId -> Strand a -> Either [String] a -- | makeOffspring (parent1, parent2) name uses the genetic -- information from parent1 and parent2 to produce a -- child with the agent ID name. The default implementation: -- --
    --
  1. Calls recombine to create a genome for the -- child.
  2. --
  3. Calls build to construct a child with this -- genome.
  4. --
makeOffspring :: (Reproductive a, RandomGen r) => a -> a -> AgentId -> Rand r (Either [String] a) -- | Provides a habitat for artificial life. module ALife.Creatur.Universe -- | A habitat containing artificial life. class (Clock (Clock u), Logger (Logger u), Database (AgentDB u), Namer (Namer u), Checklist (Checklist u), Agent (Agent u), Record (Agent u), Agent u ~ DBRecord (AgentDB u)) => Universe u where type family Agent u type family Clock u type family Logger u type family AgentDB u type family Namer u type family Checklist u clock :: Universe u => u -> Clock u setClock :: Universe u => u -> Clock u -> u logger :: Universe u => u -> Logger u setLogger :: Universe u => u -> Logger u -> u agentDB :: Universe u => u -> AgentDB u setAgentDB :: Universe u => u -> AgentDB u -> u agentNamer :: Universe u => u -> Namer u setNamer :: Universe u => u -> Namer u -> u checklist :: Universe u => u -> Checklist u setChecklist :: Universe u => u -> Checklist u -> u data SimpleUniverse a data CachedUniverse a mkSimpleUniverse :: String -> FilePath -> SimpleUniverse a mkCachedUniverse :: String -> FilePath -> Int -> CachedUniverse a -- | The current "time" (counter) in this universe currentTime :: Universe u => StateT u IO Time -- | Increment the current "time" (counter) in this universe. incTime :: Universe u => StateT u IO () -- | Write a message to the log file for this universe. writeToLog :: Universe u => String -> StateT u IO () -- | Returns the list of agents in the population. agentIds :: Universe u => StateT u IO [AgentId] -- | Returns the list of (dead) agents in the archive. archivedAgentIds :: Universe u => StateT u IO [AgentId] -- | Returns the current size of the population. popSize :: Universe u => StateT u IO Int -- | Fetches the agent with the specified ID from the population. Note: -- Changes made to this agent will not "take" until store -- is called. getAgent :: (Universe u, Serialize (Agent u)) => AgentId -> StateT u IO (Either String (Agent u)) -- | Fetches the agent with the specified ID from the archive. getAgentFromArchive :: (Universe u, Serialize (Agent u)) => AgentId -> StateT u IO (Either String (Agent u)) -- | Fetches the agents with the specified IDs from the population. getAgents :: (Universe u, Serialize (Agent u)) => [AgentId] -> StateT u IO [Agent u] -- | If the agent is alive, adds it to the population (replacing the the -- previous copy of that agent, if any). If the agent is dead, places it -- in the archive. store :: (Universe u, Serialize (Agent u)) => Agent u -> StateT u IO () -- | Generate a unique name for a new agent. genName :: Universe u => StateT u IO AgentId -- | A program involving one agent. The input parameter is the agent. The -- program must return the agent (which may have been modified). type AgentProgram u = Agent u -> StateT u IO (Agent u) -- | Run a program involving one agent withAgent :: (Universe u, Serialize (Agent u)) => AgentProgram u -> AgentId -> StateT u IO () -- | A program involving multiple agents. The input parameter is a list of -- agents. The program must return a list of agents that have been -- *modified*. The order of the output list is not important. type AgentsProgram u = [Agent u] -> StateT u IO [Agent u] withAgents :: (Universe u, Serialize (Agent u)) => AgentsProgram u -> [AgentId] -> StateT u IO () isNew :: Universe u => AgentId -> StateT u IO Bool -- | Returns the current lineup of (living) agents in the universe. Note: -- Check for endOfRound and call -- refreshLineup if needed before invoking this function. lineup :: Universe u => StateT u IO [AgentId] -- | Returns true if no agents have yet their turn at the CPU for this -- round. startOfRound :: Universe u => StateT u IO Bool -- | Returns true if the lineup is empty or if all of the agents in the -- lineup have had their turn at the CPU for this round. endOfRound :: Universe u => StateT u IO Bool -- | Creates a fresh lineup containing all of the agents in the population, -- in random order. refreshLineup :: Universe u => StateT u IO () -- | Mark the current agent done. If it is still alive, it will move to the -- end of the lineup. markDone :: Universe u => AgentId -> StateT u IO () instance GHC.Classes.Eq a => GHC.Classes.Eq (ALife.Creatur.Universe.CachedUniverse a) instance GHC.Show.Show a => GHC.Show.Show (ALife.Creatur.Universe.CachedUniverse a) instance GHC.Classes.Eq (ALife.Creatur.Universe.SimpleUniverse a) instance GHC.Show.Show (ALife.Creatur.Universe.SimpleUniverse a) instance (ALife.Creatur.Agent a, ALife.Creatur.Database.Record a) => ALife.Creatur.Universe.Universe (ALife.Creatur.Universe.SimpleUniverse a) instance (ALife.Creatur.Agent a, ALife.Creatur.Database.SizedRecord a) => ALife.Creatur.Universe.Universe (ALife.Creatur.Universe.CachedUniverse a) -- | Provides tasks that you can use with a daemon. These tasks handle -- reading and writing agents, and various other housekeeping chores, -- which reduces the amount of code you need to write. -- -- It’s also easy to write your own tasks, using these as a guide.) module ALife.Creatur.Task -- | A program involving one agent. The input parameter is the agent. The -- program must return the agent (which may have been modified). type AgentProgram u = Agent u -> StateT u IO (Agent u) -- | A program involving multiple agents. The input parameter is a list of -- agents. The program must return a list of agents that have been -- *modified*. The order of the output list is not important. type AgentsProgram u = [Agent u] -> StateT u IO [Agent u] -- | Run a program involving one agent withAgent :: (Universe u, Serialize (Agent u)) => AgentProgram u -> AgentId -> StateT u IO () withAgents :: (Universe u, Serialize (Agent u)) => AgentsProgram u -> [AgentId] -> StateT u IO () runNoninteractingAgents :: (Universe u, Serialize (Agent u)) => AgentProgram u -> StateT u IO () -> StateT u IO () -> StateT u IO () runInteractingAgents :: (Universe u, Serialize (Agent u)) => AgentsProgram u -> StateT u IO () -> StateT u IO () -> StateT u IO () simpleJob :: Universe u => Job u startupHandler :: Universe u => u -> IO u shutdownHandler :: Universe u => u -> IO () -- | Can be used as a startupHandler, shutdownHandler, startRoundProgram, -- or endRoundProgram doNothing :: Monad m => m () exceptionHandler :: Universe u => u -> SomeException -> IO u checkPopSize :: Universe u => (Int, Int) -> StateT u IO () requestShutdown :: Universe u => String -> StateT u IO ()