idiom for different implementations of same idea

Tom Pledger Tom.Pledger@peace.com
Fri, 2 Aug 2002 10:47:13 +1200


Hal Daume III writes:
 | Hi all,
 | 
 | I'm looking for some advice on what's the cleanest way to implement
 | something.
 :
 | where the main driver does something like:
 | 
 |   prepareData
 |   initialize
 |   iterate until converged
 |     doThingOne
 |     doThingTwo
 |   getResults
 | 
 | As is standard in my field (statistical natural langauge
 | processing), I have several models defined to perform task T
 | (though only the first, most basic one is implemented).  Call these
 | Model0, Model1, Model2, and so on.

If the following assumptions hold:

  - Model0.prepareData and Model0.initialize and ... and
    Model0.getResults are only ever used together

  - The `iterate until converged' aspect is the only major thing in
    the main driver which needs to be shared among the models

then I'd be inclined to reduce the amount of traffic between modules thus:

  - Export only a doItAll function from each model's module

  - Write an iterateUntilConverged function which all the models'
    modules can use, with a type signature along the lines of

    iterateUntilConverged :: (Table -> ST s Alignments) ->
                             (Alignments -> ST s Table) ->
                              Table -> ST s (Alignments, Table)

  - In each model's module:

    doItAll dataUnit
        = do let dm = prepareData dataUnit  -- "do let": the Enid Blyton idiom
             t <- initialize dm
             (as,t') <- iterateUntilConverged (doThingOne dm) (doThingTwo dm) t
             getResults dm as t'

Regards,
Tom