idiom for different implementations of same idea
Dr. Harald Holtmann
holtmannh@t-online.de
Fri, 2 Aug 2002 01:54:04 +0200
Hal Daume III writes:
> Hi all,
>
> I'm looking for some advice on what's the cleanest way to implement
> something. The basic idea is that I have a task to solve, T. There are
> many steps to solving this task, but they can be broken down into a small
> list of elementary steps:
>
> - prepareData
> - initialize
> - doThingOne
> - doThingTwo
> - getResults
>
In similar situations, especially if there is more than one useful way to
use the various parts of an algorithm, I used often prefer existentials:
data Model = forall markup table alignments. Model
{
prepareData :: Data () -> Data markup,
initialize :: Data markup -> ST s table,
doThingOne :: Data markup -> table -> ST s alignments,
doThingTwo :: Data markup -> alignments -> ST s table,
getResults :: Data markup -> table -> alignments -> String
}
So each model-module only needs to export one model record and the standard
algorithm can be implemented easily: (simplified, not checked for stupid
errors)
execModel model data =
let mark = prepareData model $ data in
runST $ do tab <- (initialize model) mark
align <- (doThingOne model) mark tab
res <- (doThingTwo model) mark align
return $ (getResults model) mark res align
Of course, by using existentials, no model internal type can escape.
> Now, I want in my executable my user to be able to say "-model=0" and so
> on in the command line and for it to use the appropriate model. Each of
> these models will go in a separate module.
This way one can even program a top-level like
doForAll data = map (\m -> execModel m data) [model0, model1, model2, ...]
which is rather useful.
Regards,
Harald