-- | Module for the core result type, and related functions--moduleText.Digestive.Result(Result(..),getResult,FormId,zeroId,mapId,formIdList,FormRange(..),incrementFormId,unitRange,isInRange,isSubRange,retainErrors,retainChildErrors)whereimportControl.Applicative(Applicative(..))importData.List(intercalate)-- | Type for failing computations--dataResulteok=Error[(FormRange,e)]|Okokderiving(Show,Eq)instanceFunctor(Resulte)wherefmap_(Errorx)=Errorxfmapf(Okx)=Ok(fx)instanceMonad(Resulte)wherereturn=OkErrorx>>=_=ErrorxOkx>>=f=fxinstanceApplicative(Resulte)wherepure=OkErrorx<*>Errory=Error$x++yErrorx<*>Ok_=ErrorxOk_<*>Errory=ErroryOkx<*>Oky=Ok$xygetResult::Resulteok->MaybeokgetResult(Error_)=NothinggetResult(Okr)=Justr-- | An ID used to identify forms--dataFormId=FormId{-- | Global prefix for the formformPrefix::String,-- | Stack indicating field. Head is most specific to this itemformIdList::[Integer]}deriving(Eq,Ord)-- | The zero ID, i.e. the first ID that is usable--zeroId::String->FormIdzeroIdp=FormId{formPrefix=p,formIdList=[0]}mapId::([Integer]->[Integer])->FormId->FormIdmapIdf(FormIdpis)=FormIdp$fisinstanceShowFormIdwhereshow(FormIdpxs)=p++"-fval["++(intercalate"."$reverse$mapshowxs)++"]"formId::FormId->IntegerformId=head.formIdList-- | A range of ID's to specify a group of forms--dataFormRange=FormRangeFormIdFormIdderiving(Eq,Show)-- | Increment a form ID--incrementFormId::FormId->FormIdincrementFormId(FormIdp(x:xs))=FormIdp$(x+1):xsincrementFormId(FormId_[])=error"Bad FormId list"unitRange::FormId->FormRangeunitRangei=FormRangei$incrementFormIdi-- | Check if a 'FormId' is contained in a 'FormRange'--isInRange::FormId-- ^ Id to check for->FormRange-- ^ Range->Bool-- ^ If the range contains the idisInRangea(FormRangebc)=formIda>=formIdb&&formIda<formIdc-- | Check if a 'FormRange' is contained in another 'FormRange'--isSubRange::FormRange-- ^ Sub-range->FormRange-- ^ Larger range->Bool-- ^ If the sub-range is contained in the larger rangeisSubRange(FormRangeab)(FormRangecd)=formIda>=formIdc&&formIdb<=formIdd-- | Select the errors for a certain range--retainErrors::FormRange->[(FormRange,e)]->[e]retainErrorsrange=mapsnd.filter((==range).fst)-- | Select the errors originating from this form or from any of the children of-- this form--retainChildErrors::FormRange->[(FormRange,e)]->[e]retainChildErrorsrange=mapsnd.filter((`isSubRange`range).fst)