[Haskell-cafe] Using Product Algebraic types

David Menendez zednenem at psualum.com
Sun Jul 4 18:38:34 EDT 2004

Sven Panne writes:

> David Menendez wrote:
> > [...] If that turned out to be a performance bottleneck, you could
> > factor out pair and write f directly: [...]
> .... or directly complain to your compiler supplier if the compiler
> in question does not do this simple transformation for you. :-)

Sure. It's a longer-term strategy, though. :-)

> Let's e.g. have a look at the code generated by GHC for the
> "inefficient" version:

Neat! Are you getting this from -ddump-simpl?

> ---------------------------------------------------------------------
> helper :: (Fitness, a) -> (Fitness, a) -> (Fitness, a)
> helper = \ds eta ->
>     case ds of
>        (f, a) -> case eta of
>                     (g, b) -> (g `plusInteger` f, b)
> rw :: Population a -> Population a
> rw = \ds ->
>     case ds of
>        Population xs ->
>           Population (case xs of
>                          (x:xs1) -> scanl helper x xs1
>                          [] -> [])
> ----------------------------------------------------------------------
> What has happened? `pair', `id', and `scanl1' were completely inlined
> and instead of the overloaded (+), an Integer-specific addition was
> chosen (`plusInteger', it's not the real name, just something for
> presentation purposes). Although these are all only O(1)
> optimizations (nothing "really clever"), one can hardly do better by
> hand... So keep the program in a form which is most comprehensible,
> even if this seems to imply some "superfluous" things at first. This
> enables you to have more time for more interesting things which could
> really have some effect on performance, like clever algorithms etc.

I completely agree.

Actually, I might have suggested using (***) or first from Control.Arrow
rather than defining pair, since they effectively do the same thing. But
looking at the Core output  I see that:

    rw2 :: Population a -> Population a
    rw2 (Population xs) = Population (scanl1 f xs)
        f (n,a) = (+n) *** id
yields (if I'm interpreting it right):

    helper2 = \ds eta ->
        case ds of
          (n,a) -> ( case eta of
                       (x,y) -> x `plusInt` y
                   , case eta of
                       (x,y) -> y

    rw2 = \ds ->
        case ds of
          Population xs ->
            Population (case xs of
                         (x:xs1) -> scanl helper2 x xs1
                         []      -> []

I don't know what to make of that. Semantically, helper2 is identical to
helper, but I'm not brave enough to look at the C output to see if they
produce different results.
David Menendez <zednenem at psualum.com> | "In this house, we obey the laws
<http://www.eyrie.org/~zednenem>      |        of thermodynamics!"

More information about the Haskell-Cafe mailing list