[Haskell-cafe] Using Product Algebraic types

David Menendez zednenem at psualum.com
Sun Jul 4 16:27:53 EDT 2004


Crypt Master writes:

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

Actually, tuples *are* product types. They just have some syntactic
sugar defined for them in the language.

For example,

    Main> ('x',5) :: (Char,Int)
    ('x',5)
    Main> ('x',5) :: (,) Char Int
    ('x',5)


> If so it it better to use tuples ? In the book the craft of func
> programing, it shows product type examples like this:
> 
> data People = Person Name Age
> type Name = String
> type Age = Int
> 
> Later it shows polymoric definitions like this:
> 
> data Pairs a = Pr a a
> 
> You mentioned that I had applied the polymorphic type "a" to Fitness,
> but but in the above example of person and people they have done the
> exactly what I did ? Used a space to seperate elements. So I am a
> little confused as to why mine didnt work.

Pairs has kind * -> *. Given a type, it constructs a new type.
(Pr has type a -> a -> Pairs a. For any type a, it takes two values of
type a and returns a value of type Pairs a).

Your code looked like:

    type Fitness = Integer
    data Population a = Population [Fitness a]

The kinds involved are:

Population :: * -> *
Fitness :: *
[] :: * -> *

It's the list type constructor that's causing you problems.
Specifically, what you have is equivalent to:

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

It's trying to apply a to Fitness, which doesn't work because Fitness is
a type, not a type constructor.

What you need is a single type containing a and Fitness. You could
either declare a new one and use that:

    data IndividualWithFitness a = IWF a Fitness
    data Population a = Population [IWF a]
    -- equivalent to:
    -- Population a = Population ([] (IWF a))

Or just use a generic pair type:

    data Population a = Population [(a,Fitness)]
    -- equivalent to:
    -- Population a = Population ([] ((,) a Fitness))

(,) has kind * -> * -> *, so it takes two type arguments ("a" and
"Fitness") and constructs a new one ("(a,Fitness)").

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

You need id if you're using pair, because pair requires two functions.
If that turned out to be a performance bottleneck, you could factor out
pair and write f directly:

    rw (Population xs) = Population (scanl1 f xs)
      where
        f (n,a) (m,b) = (n + m, a)
-- 
David Menendez <zednenem at psualum.com> <http://www.eyrie.org/~zednenem/>


More information about the Haskell-Cafe mailing list