moduleSolutions.FoldsimportData.MaybeimportData.SnocListimportData.Vect%defaulttotal---------------------------------------------------------------------------------- Recursion---------------------------------------------------------------------------------- 1anyList:(a->Bool)->Lista->BoolanyListp[]=FalseanyListp(x::xs)=casepxofFalse=>anyListpxsTrue=>TrueanyList':(a->Bool)->Lista->BoolanyList'pNil=FalseanyList'p(x::xs)=px||anyListpxsallList:(a->Bool)->Lista->BoolallListp[]=TrueallListp(x::xs)=casepxofTrue=>allListpxsFalse=>FalseallList':(a->Bool)->Lista->BoolallList'pNil=TrueallList'p(x::xs)=px&&allListpxs-- 2findList:(a->Bool)->Lista->MaybeafindListf[]=NothingfindListf(x::xs)=iffxthenJustxelsefindListfxs-- 3collectList:(a->Maybeb)->Lista->MaybebcollectListf[]=NothingcollectListf(x::xs)=casefxofJustvb=>JustvbNothing=>collectListfxs-- Note utility function `Data.Maybe.toMaybe` in the implementationlookupList:Eqa=>a->List(a,b)->MaybeblookupListva=collectList(\(k,v)=>toMaybe(k==va)v)-- 4mapTR':(a->b)->Lista->ListbmapTR'f=goLinwherego:SnocListb->Lista->Listbgosx[]=sx<>>Nilgosx(x::xs)=go(sx:<fx)xs-- 5filterTR':(a->Bool)->Lista->ListafilterTR'f=goLinwherego:SnocLista->Lista->Listagosx[]=sx<>>Nilgosx(x::xs)=iffxthengo(sx:<x)xselsegosxxs-- 6mapMayTR:(a->Maybeb)->Lista->ListbmapMayTRf=goLinwherego:SnocListb->Lista->Listbgosx[]=sx<>>Nilgosx(x::xs)=casefxofJustvb=>go(sx:<vb)xsNothing=>gosxxscatMaybesTR:List(Maybea)->ListacatMaybesTR=mapMayTRid-- 7concatTR:Lista->Lista->ListaconcatTRxsys=(Lin<><xs)<>>ys-- 8bindTR:Lista->(a->Listb)->ListbbindTRxsf=goLinxswherego:SnocListb->Lista->Listbgosx[]=sx<>>Nilgosx(x::xs)=go(sx<><fx)xsjoinTR:List(Lista)->ListajoinTR=goLinwherego:SnocLista->List(Lista)->Listagosx[]=sx<>>Nilgosx(x::xs)=go(sx<><x)xs-- Using the connection between join and bind:-- yielding a tail recursive implementation as bindTR is.joinTR':List(Lista)->ListajoinTR'xss=bindTRxssid---------------------------------------------------------------------------------- A few Notes on Totality Checking--------------------------------------------------------------------------------recordTreeawhereconstructorNodevalue:aforest:List(Treea)Forest:Type->TypeForest=List.Treeexample:TreeBits8example=Node0[Node1[],Node2[Node3[],Node4[Node5[]]]]mutualtreeSize:Treea->NattreeSize(Node_forest)=S $ forestSizeforestforestSize:Foresta->NatforestSize[]=0forestSize(x::xs)=treeSizex+forestSizexs-- 1mutualtreeDepth:Treea->NattreeDepth(Node_forest)=S $ forestDepthforestforestDepth:Foresta->NatforestDepth[]=0forestDepth(x::xs)=max(treeDepthx)(forestDepthxs)-- 2-- It's often easier to write complex interface implementations-- via a utility function.---- Of course, we could also use a `mutual` block as with-- `treeSize` and `forestSize` here.treeEq:Eqa=>Treea->Treea->BooltreeEq(Nodev1f1)(Nodev2f2)=v1==v2&&gof1f2wherego:Foresta->Foresta->Boolgo[][]=Truego(x::xs)(y::ys)=treeEqxy&&goxsysgo__=FalseEqa=>Eq(Treea)where(==)=treeEq-- 3treeMap:(a->b)->Treea->TreebtreeMapf(Nodevalueforest)=Node(fvalue)(goforest)wherego:Foresta->Forestbgo[]=[]go(x::xs)=treeMapfx::goxsFunctorTreewheremap=treeMap-- 4treeShow:Showa=>Prec->Treea->StringtreeShowp(Nodevalueforest)=showConp"Node" $ showArgvalue++caseforestof[]=>" []"x::xs=>" ["++treeShowOpenx++goxs++"]"wherego:Foresta->Stringgo[]=""go(y::ys)=", "++treeShowOpeny++goysShowa=>Show(Treea)whereshowPrec=treeShow-- 5mutualtreeToVect:(tr:Treea)->Vect(treeSizetr)atreeToVect(Nodevalueforest)=value::forestToVectforestforestToVect:(f:Foresta)->Vect(forestSizef)aforestToVect[]=[]forestToVect(x::xs)=treeToVectx++forestToVectxs---------------------------------------------------------------------------------- Interface Foldable---------------------------------------------------------------------------------- 1dataCrud:(i:Type)->(a:Type)->TypewhereCreate:(value:a)->CrudiaUpdate:(id:i)->(value:a)->CrudiaRead:(id:i)->CrudiaDelete:(id:i)->CrudiaFoldable(Crudi)wherefoldraccst(Createvalue)=accvaluestfoldraccst(Update_value)=accvaluestfoldr_st(Read_)=stfoldr_st(Delete_)=stfoldlaccst(Createvalue)=accstvaluefoldlaccst(Update_value)=accstvaluefoldl_st(Read_)=stfoldl_st(Delete_)=stnull(Create_)=Falsenull(Update__)=Falsenull(Read_)=Truenull(Delete_)=TruefoldMapf(Createvalue)=fvaluefoldMapf(Update_value)=fvaluefoldMap_(Read_)=neutralfoldMap_(Delete_)=neutralfoldlMaccst(Createvalue)=accstvaluefoldlMaccst(Update_value)=accstvaluefoldlM_st(Read_)=purestfoldlM_st(Delete_)=puresttoList(Createv)=[v]toList(Update_v)=[v]toList(Read_)=[]toList(Delete_)=[]-- 2dataResponse:(e,i,a:Type)->TypewhereCreated:(id:i)->(value:a)->ResponseeiaUpdated:(id:i)->(value:a)->ResponseeiaFound:(values:Lista)->ResponseeiaDeleted:(id:i)->ResponseeiaError:(err:e)->ResponseeiaFoldable(Responseei)wherefoldraccst(Created_value)=accvaluestfoldraccst(Updated_value)=accvaluestfoldraccst(Foundvalues)=foldraccstvaluesfoldr_st(Deleted_)=stfoldr_st(Error_)=stfoldlaccst(Created_value)=accstvaluefoldlaccst(Updated_value)=accstvaluefoldlaccst(Foundvalues)=foldlaccstvaluesfoldl_st(Deleted_)=stfoldl_st(Error_)=stnull(Created__)=Falsenull(Updated__)=Falsenull(Foundvalues)=nullvaluesnull(Deleted_)=Truenull(Error_)=TruefoldMapf(Created_value)=fvaluefoldMapf(Updated_value)=fvaluefoldMapf(Foundvalues)=foldMapfvaluesfoldMapf(Deleted_)=neutralfoldMapf(Error_)=neutraltoList(Created_value)=[value]toList(Updated_value)=[value]toList(Foundvalues)=valuestoList(Deleted_)=[]toList(Error_)=[]foldlMaccst(Created_value)=accstvaluefoldlMaccst(Updated_value)=accstvaluefoldlMaccst(Foundvalues)=foldlMaccstvaluesfoldlM_st(Deleted_)=purestfoldlM_st(Error_)=purest-- 3dataList01:(nonEmpty:Bool)->Type->TypewhereNil:List01Falsea(::):a->List01Falsea->List01nealist01ToList:List01nea->Listalist01ToList=goLinwherego:SnocLista->List01ne'a->Listagosx[]=sx<>>Nilgosx(x::xs)=go(sx:<x)xslist01FoldMap:Monoidm=>(a->m)->List01nea->mlist01FoldMapf=goneutralwherego:m->List01ne'a->mgovm[]=vmgovm(x::xs)=go(vm<+>fx)xsFoldable(List01ne)wherefoldraccst[]=stfoldraccst(x::xs)=accx(foldraccstxs)foldlaccst[]=stfoldlaccst(x::xs)=foldlacc(accstx)xsnull[]=Truenull(_::_)=FalsetoList=list01ToListfoldMap=list01FoldMapfoldlM_st[]=purestfoldlMfst(x::xs)=fstx>>=\st'=>foldlMfst'xs-- 4mutualfoldrTree:(el->st->st)->st->Treeel->stfoldrTreefv(Nodevalueforest)=fvalue(foldrForestfvforest)foldrForest:(el->st->st)->st->Forestel->stfoldrForest_v[]=vfoldrForestfv(x::xs)=foldrTreef(foldrForestfvxs)xmutualfoldlTree:(st->el->st)->st->Treeel->stfoldlTreefv(Nodevalueforest)=foldlForestf(fvvalue)forestfoldlForest:(st->el->st)->st->Forestel->stfoldlForest_v[]=vfoldlForestfv(x::xs)=foldlForestf(foldlTreefvx)xsmutualfoldMapTree:Monoidm=>(el->m)->Treeel->mfoldMapTreef(Nodevalueforest)=fvalue<+>foldMapForestfforestfoldMapForest:Monoidm=>(el->m)->Forestel->mfoldMapForest_[]=neutralfoldMapForestf(x::xs)=foldMapTreefx<+>foldMapForestfxsmutualtoListTree:Treeel->ListeltoListTree(Nodevalueforest)=value::toListForestforesttoListForest:Forestel->ListeltoListForest[]=[]toListForest(x::xs)=toListTreex++toListForestxsmutualfoldlMTree:Monadm=>(st->el->mst)->st->Treeel->mstfoldlMTreefv(Nodevalueforest)=fvvalue>>=\v'=>foldlMForestfv'forestfoldlMForest:Monadm=>(st->el->mst)->st->Forestel->mstfoldlMForest_v[]=purevfoldlMForestfv(x::xs)=foldlMTreefvx>>=\v'=>foldlMForestfv'xsFoldableTreewherefoldr=foldrTreefoldl=foldlTreefoldMap=foldMapTreefoldlM=foldlMTreenull_=FalsetoList=toListTree-- 5recordComp(f,g:Type->Type)(a:Type)whereconstructorMkCompunComp:f(ga)Foldablef=>Foldableg=>Foldable(Compfg)wherefoldrfst(MkCompv)=foldr(flip $ foldrf)stvfoldlfst(MkCompv)=foldl(foldlf)stvfoldMapf(MkCompv)=foldMap(foldMapf)vfoldlMfst(MkCompv)=foldlM(foldlMf)stvtoList(MkCompv)=foldMaptoListvnull(MkCompv)=allnullvrecordProduct(f,g:Type->Type)(a:Type)whereconstructorMkProductfst:fasnd:gaFoldablef=>Foldableg=>Foldable(Productfg)wherefoldrfst(MkProductvw)=foldrf(foldrfstw)vfoldlfst(MkProductvw)=foldlf(foldlfstv)wfoldMapf(MkProductvw)=foldMapfv<+>foldMapfwtoList(MkProductvw)=toListv++toListwnull(MkProductvw)=nullv&&nullwfoldlMfst(MkProductvw)=foldlMfstv>>=\st'=>foldlMfst'w---------------------------------------------------------------------------------- Tests--------------------------------------------------------------------------------iterateTR:Nat->(a->a)->a->ListaiterateTRkf=gokLinwherego:Nat->SnocLista->a->Listago0sx_=sx<>>Nilgo(Sk)sxx=gok(sx:<x)(fx)values:ListIntegervalues=iterateTR100000(+1)0main:IO()main=doprintLn.length $ mapTR'(*2)valuesprintLn.length $ filterTR'(\n=>n`mod`2==0)valuesprintLn.length $ mapMayTR(\n=>toMaybe(n`mod`2==1)"foo")valuesprintLn.length $ concatTRvaluesvaluesprintLn.length $ bindTR[1..500](\n=>iterateTRn(+1)n)