[Haskell-cafe] Possible Improvements

Don Stewart dons at galois.com
Mon Dec 3 00:54:05 EST 2007


catamorphism:
> On 12/2/07, Don Stewart <dons at galois.com> wrote:
> > prstanley:
> > > Hi
> > > data Tree = Leaf Int | Node Tree Int Tree
> > >
> > > occurs :: Int -> Tree -> Bool
> > > occurs m (Leaf n) = m == n
> > > occurs m (Node l n r) = m == n || occurs m l || occurs m r
> > >
> > > It works but I'd like to know if it can be improved in any way.
> >
> > You could probably get away with:
> >
> >     data Tree = Leaf !Int | Node Tree !Int Tree
> >
> > but that's a minor issue.
> >
> 
> IMO, there's no reason to even think about putting in the strictness
> annotations unless you've identified this datatype as part of a
> performance bottleneck in production code. Otherwise, there's no need
> to clutter your code and your mind with them :-)

Very true ("a minor issue").

However, *rarely* do you want lazines in the atomic types
(Int,Char,Word,Integer, et al)

A little test:

    main = do
        n <- getArgs >>= readIO . head
        let t = make (n*2) n
        print (check t)

    make :: Int -> Int -> Tree
    make i 0 = Node (Leaf 0) i (Leaf 0)
    make i d = Node (make (i2-1) d2) i (make i2 d2)
      where i2 = 2*i
            d2 = d-1

    check :: Tree -> Int
    check (Leaf _)     = 0
    check (Node l i r) = i + check l - check r

Fully lazy:

    data Tree = Leaf Int | Node Tree Int Tree

    $ time ./A 25
    49           
    ./A 25  18.20s user 0.04s system 99% cpu 18.257 total
                                             ^^^^^^
    3556K heap use.

Strict in the elements, lazy in the spine:

    data Tree = Leaf !Int | Node Tree !Int Tree

    $ time ./A 25      
    49
    ./A 25  14.41s user 0.03s system 99% cpu 14.442 total
                                             ^^^^^^
    3056K heap use.

You'll be hard pressed to do better in C here.
Finally, strict in the spine and elements:

    data Tree = Leaf !Int | Node !Tree !Int !Tree

    $ time ./A 25      
    A: out of memory (requested 1048576 bytes)
    ./A 25  11.46s user 2.60s system 97% cpu 14.379 total

    657M heap use
    ^^^^
Lesson:

 * Full strictness       == teh suckness. 
 * Mixed lazy and strict == flexible and efficient data types.

Makes me wonder why Map is strict in the spine,

    data Map k a  = Tip 
                  | Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)

Anyone know?

Cheers,
  Don


More information about the Libraries mailing list