-- |-- Code to read configuration files.---- Author: mjsottile\@computer.org--moduleGEP.Util.ConfigurationReader(readParameters)whereimportGEP.ParamsimportGEP.TypesimportSystem.IOimportMaybe---- given a list of pairs mapping keys to values, lookup the various-- parameters and populate the rates, genome, and simparams structures--extractParameters::[(String,String)]->(Rates,Genome,SimParams)extractParametersconfig=(r,g,s)wheres=SimParams{popSize=fromJust(lookupInt"populationSize"config),selectionRange=fromJust(lookupDouble"selectionRange"config),maxFitness=fromJust(lookupDouble"maxFitness"config),numGenerations=fromJust(lookupInt"numGenerations"config),maxISLen=fromJust(lookupInt"maxISLen"config),maxRISLen=fromJust(lookupInt"maxRISLen"config),rouletteExponent=fromJust(lookupDouble"rouletteExponent"config)}r=Rates{pMutate=fromJust(lookupDouble"rateMutate"config),p1R=fromJust(lookupDouble"rate1R"config),p2R=fromJust(lookupDouble"rate2R"config),pGR=fromJust(lookupDouble"rateGR"config),pIS=fromJust(lookupDouble"rateIS"config),pRIS=fromJust(lookupDouble"rateRIS"config),pGT=fromJust(lookupDouble"rateGT"config)}g=Genome{terminals=fromJust(lookupString"genomeTerminals"config),nonterminals=fromJust(lookupString"genomeNonterminals"config),geneConnector=fromJust(lookupChar"genomeGeneConnector"config),maxArity=fromJust(lookupInt"genomeMaxArity"config),numGenes=fromJust(lookupInt"genomeNumGenes"config),headLength=fromJust(lookupInt"genomeHeadLength"config)}---- function visible to the outside world. passes in a string representing-- the filename of the configuration, and passes back the rates,-- genome, and simparams structures. Expected to be called from within the-- IO monad--readParameters::String->IO(Rates,Genome,SimParams)readParametersfilename=doconfig<-readConfigurationfilenamereturn$extractParametersconfig---- lookup helpers: float, int, char, and string versions--lookupDouble::String->[(String,String)]->MaybeDoublelookupDouble_[]=NothinglookupDoublek((key,value):_)|(k==key)=Just(readvalue)lookupDoublek((_,_):kvs)|otherwise=lookupDoublekkvslookupInt::String->[(String,String)]->MaybeIntlookupInt_[]=NothinglookupIntk((key,value):_)|(k==key)=Just(readvalue)lookupIntk((_,_):kvs)|otherwise=lookupIntkkvslookupString::String->[(String,String)]->MaybeStringlookupString_[]=NothinglookupStringk((key,value):_)|(k==key)=JustvaluelookupStringk((_,_):kvs)|otherwise=lookupStringkkvslookupChar::String->[(String,String)]->MaybeCharlookupChar_[]=NothinglookupChark((key,value):_)|(k==key)=Just(headvalue)lookupChark((_,_):kvs)|otherwise=lookupCharkkvs---- given a string, remove whitespace--removeWhitespace::String->StringremoveWhitespace[]=[]removeWhitespace(x:xs)|(x==' ')=removeWhitespacexsremoveWhitespace(x:xs)|(x=='\t')=removeWhitespacexsremoveWhitespace(x:xs)|otherwise=x:(removeWhitespacexs)---- split a line formatted as "KEY=VALUE", removing whitespace--splitLine::String->(String,String)splitLinel=(front,back)wherecleaned=removeWhitespacelfront=takeWhile(\i->not(i=='='))cleanedback=drop1(dropWhile(\i->not(i=='='))cleaned)---- read a file handle and return all of the lines in the file--fileToLines::Handle->IO[String]fileToLinesh=doeof<-hIsEOFh(ifeofthenreturn[]elsedoline<-hGetLinehremainder<-fileToLineshreturn$(line:remainder))---- given a filename, open the file, read the lines, and then split them-- into key/value pairs assuming a "KEY=VALUE" format per line--readConfiguration::String->IO[(String,String)]readConfigurationfilename=dohandle<-openFilefilenameReadModefileLines<-fileToLineshandlereturn$map(\i->splitLinei)fileLines