moduleLanguage.Sifflet.Util(-- | Parser UtilitiesSuccFail(Succ,Fail),parsef,parseInt,parseDouble,parseVerbatim-- | String Utilities,par-- Output Utilities,putCatsLn,putCatLn,info,fake,stub-- | Error Reporting,errcat,errcats-- | List Utilities,map2,mapM2,adjustAList,adjustAListM,insertLastLast,insertLast)whereimportControl.Monad()-- SuccFail: the result of an attempt, succeeds or failsdataSuccFaila=Succa-- value|FailString-- error messagederiving(Eq,Read,Show)instanceMonadSuccFailwhereSuccval>>=f=fvalFailerr>>=_f=Failerrreturn=Succfail=Fail-- PARSER UTILITIESparsef::(Reada)=>String->String->String->SuccFailaparseftypeNameinputLabelinput=casereadsinputof[(value,"")]->Succvalue[(_,more)]->Fail$inputLabel++": extra characters after "++typeName++": "++more_->Fail$inputLabel++": cannot parse as "++typeName++": "++inputparseInt::String->String->SuccFailIntparseInt=parsef"integer"parseDouble::String->String->SuccFailDoubleparseDouble=parsef"real number"parseVerbatim::String->String->SuccFailStringparseVerbatim_label=Succ-- | Enclose in parentheses, like a Lisp function call.-- Example: par "foo" ["x", "y"] = "(foo x y)"par::String->[String]->Stringparfxs="("++unwords(f:xs)++")"-- | Write a list of words, separated by spacesputCatsLn::[String]->IO()putCatsLn=putStrLn.unwords-- | Write a list of words, not separated by spacesputCatLn::[String]->IO()putCatLn=putStrLn.concatinfo::(Showt)=>t->IO()info=printfake::String->IO()fakewhat=putStrLn$"Faking "++what++"..."stub::String->IO()stubname=putStrLn$"Stub for "++name-- ERROR REPORTING-- | Signal an error using a list of strings to be concatenatederrcat::[String]->aerrcat=error.concat-- | Signal an error using a list of strings to be concatenated-- with spaces between (unwords).errcats::[String]->aerrcats=error.unwords-- LIST UTILITIES-- | Generalization of map to lists of listsmap2::(a->b)->[[a]]->[[b]]map2frows=-- map (\ row -> map f row) rowsmap(mapf)rows-- | Generalization of mapM to lists of listsmapM2::(Monadm)=>(a->mb)->[[a]]->m[[b]]mapM2frows=-- mapM (\ row -> mapM f row) rowsmapM(mapMf)rows-- | Insert an item into a list of lists of items,-- making it the last element in the last sublistinsertLastLast::[[a]]->a->[[a]]insertLastLastxssx=initxss++[insertLast(lastxss)x]-- | Insert an item in a list of items, making it the last elementinsertLast::[a]->a->[a]insertLastxsx=xs++[x]-- | Update a value at a given key by applying a function.-- Similar to Data.Map.adjust.-- This implementation, using map, could be inefficient-- if the key to be updated is near the front of a long list.adjustAList::(Eqk)=>k->(v->v)->[(k,v)]->[(k,v)]adjustAListkeyfalist=map(\(k,v)->ifk==keythen(k,fv)else(k,v))alist-- | Monadic generalization of adjustAList -- Same caution re. inefficiencyadjustAListM::(Eqk,Monadm)=>k->(v->mv)->[(k,v)]->m[(k,v)]adjustAListMkeyfalist=mapM(\(k,v)->ifk==keythendo{v'<-fv;return(k,v')}elsereturn(k,v))alist