# [Haskell-cafe] Using Product Algebraic types

Stefan Holdermans sholderm at students.cs.uu.nl
Sun Jul 4 16:18:35 EDT 2004

```Crypt Master,

> data Population a = Population [(Fitness, a)]

CM> Am I correct in assuming that your definition of
CM> Popoulation is now using tuple and not product types ?

Yes, you are. If you really want to use a new product, you can of course:

> data FitnessProd a  = FProd Fitness a
> data Population' a  = Population' [FitnessProd a]

A pair, i.e. a binary tuple, is a product type itself, be it one with
special syntax. You can think of it as being defined by

< data (,) a b = (,) a b

CM> If so it it better to use tuples?

As always: it depends. I guess it is a design matter. If your product really
represents some distinct entity, you might want to go for a new data type.
If your product is merely just a pair, using tuples is more straightforward.

CM> You mentioned that I had applied the polymorphic type
CM> "a" to Fitness, but but in the above example of person
CM> and people they have done the exactly what I did ?
CM> Used a space to seperate elements. So I am a little
CM> confused as to why mine didnt work.

As I said, you encountered a kind error. You have Paul Hudak's book, haven't
you? In section 18.3 he explains how kinding works. You may want to read

To see where things went wrong, examine your definitions once again. First,
you defined Fitness to be a synonym of Integer.

> type Fitness = Integer

Integer is a data type that does not take any type arguments. You can think
of it as being defined by

< data Integer = ... | -2 | -1 | 0 | 1 | 2 | ...

A type constructor that does not take any type arguments to produce a type
is said to be of kind *. Here, Integer is of kind *, and, therefore, so is
Fitness.

Now consider, the following type:

> data Fork a = Fork a a

The type constructor Fork takes one type argument and therefore it has a
function kind: k -> *, for some k. From the right-hand side we can infer
that k is *, so the kind of Fork is * -> *. This means that the type
constructor Fork can be applied on a type of kind *, for example Integer.

> type ForkedInteger = Fork Integer

However, Fitness, which is of kind *, cannot be applied to any type
argument, so the following is illegal:

< type FitnessedInteger = Fitness Integer -- kind error!

This is exactly what you tried: applying Fitness to some other type.

CM> Can I ask one question, I am not concerned with
CM> performance at this point, but what sort of overhead
CM> does a function like id have. It seems unneccesary to
CM> me ( I am not critising your solution, I am vert
CM> thankfull for your help in a large populations you
CM> will  land up doing a fair amount of extra but simple
CM> "reductions" ( I hope thats the right word. ) just to
CM> "copy" the unkown "a". Or does it have to be a
CM> function for some reason and so you had to use "id" ?

> rw (Population xs) =  Population (scanl1 f xs)
>                         where f (n, a) = (+ n) `pair` id
> pair       :: (a -> c) -> (b -> d) -> (a, b) -> (c, d)
> f `pair` g =  h
>                 where h (a, b) = (f a, g b)

Well, the unknown a-values should be transferred from the input list to the
output list, so there's not much choice here. In fact, the f function does
nothing more than

> f               :: (Fitness, a) -> (Fitness, a)
>                    -> (Fitness, a)
> f (m, _) (n, a) =  (n + m, a)

which seems quite minimal.

HTH,

Stefan

```