hevolisa-0.0: Hevolisa/Tools.hs
--
-- Module : Tools
-- Copyright : (c) Daniel Neun 2008
-- License : BSD-style
-- Maintainer : daniel.neun@gmx.de
-- Stability : experimental
-- Portability : portable
module Hevolisa.Tools (
-- * Classes
Mutable (mutate),
Points (pointCount),
RandomInit (randomInit),
-- * Utility functions
when,
willMutate,
maybeMutate,
getRandomNumber,
-- * List index functions
addElem,
removeElem,
moveElem
) where
import Random
-- |Instances of Mutable can mutate their DNA
class Mutable a where
-- |Perform a genetic mutation in a random way
mutate :: a -> IO a
-- |Count the points
class Points a where
-- |Count the points
pointCount :: (Integral b) => a -> b
-- |Initialize a shape with random values
class RandomInit a where
-- |Action that returns a shape with random values
randomInit :: IO a
-- |Decide whether it`s time for a mutation
willMutate :: Integer -- ^ Mutation rate
-> IO Bool -- ^ True: Mutate
willMutate mutationRate = do k <- getRandomNumber 0 mutationRate
return (k == 1)
-- |Get a random number between min and max
getRandomNumber :: Random a =>
a -- ^ Minimum
-> a -- ^ Maximum
-> IO a -- ^ Random number action
getRandomNumber x y = getStdRandom (randomR (x,y))
-- |Helper function to get rid of if-then-else
when :: Bool -- ^ constraint
-> (a -> IO a) -- ^ function
-> a -- ^ unchaged value to pass through
-> Bool -- ^ mutate?
-> IO a -- ^ result action
when constraint f = flip (awhen constraint f)
where awhen :: Bool -> (a -> IO a) -> Bool -> (a -> IO a)
awhen constraint f mutate | mutate && constraint = f
| otherwise = return
-- |Perform a mutation action when it`s time to do so
maybeMutate :: Integer -- ^ Mutation rate
-> IO a -- ^ Mutation action
-> a -- ^ Unchanged value to pass through
-> IO a -- ^ Composed action
maybeMutate rate action unchanged = do mutate <- willMutate rate
if mutate then action else return unchanged
-- |Move a list element from index to index
moveElem :: Int -- ^ from index
-> Int -- ^ to index
-> [a] -- ^ original list
-> [a] -- ^ result
moveElem from to lst = addElem elem to $ removeElem from lst
where elem = lst !! from
-- |Remove an item at index position from list
removeElem :: Int -- ^ index
-> [a] -- ^ original list
-> [a] -- ^ result
removeElem n lst = left ++ right
where left = take n lst
right = drop (n + 1) lst
-- |Add an item at index position to list
addElem :: a -- ^ element
-> Int -- ^ index
-> [a] -- ^ original list
-> [a] -- ^ result
addElem item index lst = left ++ [item] ++ right
where left = take index lst
right = drop index lst