123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196open!ImportincludeEither_intfmoduleArray=Array0moduleList=List0includeEither0letswap=function|Firstx->Secondx|Secondx->Firstx;;letis_first=function|First_->true|Second_->false;;letis_second=function|First_->false|Second_->true;;letvalue(Firstx|Secondx)=xletvalue_mapt~first~second=matchtwith|Firstx->firstx|Secondx->secondx;;letiter=value_mapletmapt~first~second=matchtwith|Firstx->First(firstx)|Secondx->Second(secondx);;letfirstx=Firstxletsecondx=Secondxletequaleq1eq2t1t2=matcht1,t2with|Firstx,Firsty->eq1xy|Secondx,Secondy->eq2xy|First_,Second_|Second_,First_->false;;letinvariantfs=function|Firstx->fx|Secondy->sy;;moduleMake_focused(M:sigtype(+'a,+'b)tvalreturn:'a->('a,_)tvalother:'b->(_,'b)tvaleither:('a,'b)t->return:('a->'c)->other:('b->'c)->'cvalcombine:('a,'d)t->('b,'d)t->f:('a->'b->'c)->other:('d->'d->'d)->('c,'d)tvalbind:('a,'b)t->f:('a->('c,'b)t)->('c,'b)tend)=structincludeMopenWith_returnletmapt~f=bindt~f:(funx->return(fx))includeMonad.Make2(structtypenonrec('a,'b)t=('a,'b)tletreturn=returnletbind=bindletmap=`Custommapend)moduleApp=Applicative.Make2(structtypenonrec('a,'b)t=('a,'b)tletreturn=returnletapplyt1t2=bindt1~f:(funf->bindt2~f:(funx->return(fx)))letmap=`Custommapend)includeAppletcombine_all=letrecother_loopfacc=function|[]->otheracc|t::ts->eithert~return:(fun_->other_loopfaccts)~other:(funo->other_loopf(facco)ts)inletrecreturn_loopfacc=function|[]->return(List.revacc)|t::ts->eithert~return:(funx->return_loopf(x::acc)ts)~other:(funo->other_loopfots)infunts~f->return_loopf[]ts;;letcombine_all_unit=letrecother_loopfacc=function|[]->otheracc|t::ts->eithert~return:(fun()->other_loopfaccts)~other:(funo->other_loopf(facco)ts)inletrecreturn_loopf=function|[]->return()|t::ts->eithert~return:(fun()->return_loopfts)~other:(funo->other_loopfots)infunts~f->return_loopfts;;letto_optiont=eithert~return:Option.some~other:(fun_->None)letvaluet~default=eithert~return:Fn.id~other:(fun_->default)letwith_returnf=with_return(funret->other(f(With_return.prependret~f:return)));;endmoduleFirst=Make_focused(structtypenonrec('a,'b)t=('a,'b)tletreturn=firstletother=secondleteithert~return~other=matchtwith|Firstx->returnx|Secondy->othery;;letcombinet1t2~f~other=matcht1,t2with|Firstx,Firsty->First(fxy)|Secondx,Secondy->Second(otherxy)|Secondx,_|_,Secondx->Secondx;;letbindt~f=matchtwith|Firstx->fx(* Reuse the value in order to avoid allocation. *)|Second_asy->y;;end)moduleSecond=Make_focused(structtypenonrec('a,'b)t=('b,'a)tletreturn=secondletother=firstleteithert~return~other=matchtwith|Secondy->returny|Firstx->otherx;;letcombinet1t2~f~other=matcht1,t2with|Secondx,Secondy->Second(fxy)|Firstx,Firsty->First(otherxy)|Firstx,_|_,Firstx->Firstx;;letbindt~f=matchtwith|Secondx->fx(* Reuse the value in order to avoid allocation, like [First.bind] above. *)|First_asy->y;;end)moduleExport=structtype('f,'s)_either=('f,'s)t=|Firstof'f|Secondof'send