David Menendez zednenem at psualum.com
Fri Jul 2 22:33:13 EDT 2004

```Crypt Master writes:

>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
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 <zednenem at psualum.com> <http://www.eyrie.org/~zednenem/>
```