I am trying to create a function that recursively plays all possible tic-tac-toe games using a genetic algorithm, and then returns a tuple (wins, losses, connections). However, the function below always overflows the stack when called like this:
scoreOne :: UnscoredPlayer -> [String] -> ScoredPlayer scoreOne player boards = ScoredPlayer (token player) (chromosome player) (evaluateG $! testPlayer player boards) ... let results = map (\x->scoreOne x boards) players print (maximum results)
where players is a list of chromosomes. Overflow does not occur with only 1 player, but with two cases.
EDIT: if a function is called as follows, it does not overflow the stack.
let results = map (\player -> evaluateG (testPlayer player boards)) players print (maximum results)
However, the next path overflows the stack.
let results = map (\player -> ScoredPlayer (token player) (chromosome player) (evaluateG $! testPlayer player boards)) players
For reference, ScoredPlayer defined as (a string is a playerโs token, [Int] is a chromosome, and Float is an estimate):
data ScoredPlayer = ScoredPlayer String ![Int] !Float deriving (Eq)
From what I know about Haskell, the playAll' function is not tail recursion, because the call to foldl' that I use performs further processing of the results of the function. However, I have no idea how to eliminate the foldl' call, since it should ensure that all possible games are played. Is there a way to restructure a function so that it is recursive (or at least doesn't overflow the stack)?
Thanks in advance, and sorry for the massive list of codes.
playAll' :: (Num a) => UnscoredPlayer -> Bool -> String -> [String] -> (a,a,a) -> (a,a,a) playAll' player playerTurn board boards (w,ls,t)= if won == self then (w+1,ls,t) -- I won this game else if won == enemy then (w,ls+1,t) -- My enemy won this game else if '_' `notElem` board then (w,ls,t+1) -- It a tie else if playerTurn then --My turn; make a move and try all possible combinations for the enemy playAll' player False (makeMove ...) boards (w,ls,t) else --Try each possible move against myself (foldl' (\(x,y,z) (s1,s2,s3) -> (x+s1,y+s2,z+s3)) (w,ls,t) [playAll' player True newBoard boards (w,ls,t)| newBoard <- (permute enemy board)]) where won = winning board --if someone has one, who is it? enemy = (opposite.token) player --what player is my enemy? self = token player --what player am I?