
From what I can see, a key difficulty you're having is with the "evolvepopulation" function. You've given it the type a -> a, which
Crypt Master writes: pretty much requires it to be an identity function, because it's not allowed to make any assumptions about the values it takes. To make things easier to read, try defining types for Population and Individual (they can always be generalized later).
type Individual = Int type Population = [Individual]
Then you want
evolve :: Population -> Population
It looks like you're defining evolution as the composition of mutate, cross, and select, but got tripped up by the order of evaluation. Specifically, "mutate cross select p" is the same as "((mutate cross) select) p", which probably isn't what you want. If you have:
mutate :: Population -> Population cross :: Population -> Population select :: Population -> Population
Then you could define
evolve p = mutate (cross (select p))
-- alternative: -- evolve = mutate . cross . select
Starting from an initial population, you want to generate a sequence by iterating evolve, starting from an initial population. Haskell provides a function "iterate" for this purpose, or you can define your own.
gaSolutionSpace :: Population -> [Population] gaSolutionSpace p = p : gaSolutionSpace (evolve p)
-- alternative: -- gaSolutionSpace = iterate evolve
Note that the type you want is Population -> [Population]. Now, we get to the problem. You were trying take 5 gaSolutionSpace [1,2,3,4,5] But take :: Int -> [a] -> [a]. That means the second argument has to be a list, not a function which produces a list. But that's easily solved by some parentheses: take 5 (gaSolutionSpace [1,2,3,4,5]) Or you can define another function:
generate :: Int -> Population -> [Population] generate n p = take n (gaSolutionSpace p)
-- alternative: -- generate n = take n . gaSolutionSpace
I found it helpful to remember that you can think of a function f :: a
-> b -> c as taking two arguments of types a and b and returning a
result c, or as taking a single argument of type a and returning a
result of type b -> c. Once you become comfortable with partial
application, a lot of Haskell code starts to make more sense.
--
David Menendez