123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149open!CoremoduleArray=Base.ArraymoduleList=Base.ListmoduleOption=Base.OptionmoduleSequence=Base.SequencemoduleNode=structtype'at={value:'a;children:'atlist}endopenNodetype'at={compare:'a->'a->int;length:int;heap:'aNode.toption}letcreate~compare={compare;length=0;heap=None}letmerge~compare({value=e1;children=nl1}asn1)({value=e2;children=nl2}asn2)=ifcomparee1e2<0then{value=e1;children=n2::nl1}else{value=e2;children=n1::nl2};;letmerge_pairs~comparet=letrecloopacct=matchtwith|[]->acc|[head]->head::acc|head::next1::next2->loop(merge~compareheadnext1::acc)next2inmatchloop[]twith|[]->None|[h]->Someh|x::xs->Some(List.foldxs~init:x~f:(merge~compare));;letadd{compare;length;heap}e=letnew_node={value=e;children=[]}inletheap=matchheapwith|None->new_node|Someheap->merge~comparenew_nodeheapin{compare;length=length+1;heap=Someheap};;lettop_exnt=matcht.heapwith|None->failwith"Fheap.top_exn called on an empty heap"|Some{value;_}->value;;lettopt=trySome(top_exnt)with|_->None;;letpop_exn{compare;length;heap}=matchheapwith|None->failwith"Heap.pop_exn called on an empty heap"|Some{value;children}->letnew_heap=merge_pairs~comparechildreninlett'={compare;length=length-1;heap=new_heap}invalue,t';;letpopt=trySome(pop_exnt)with|_->None;;letpop_min=popletpop_min_exn=pop_exnletremove_topt=trylet_,t'=pop_exntinSomet'with|_->None;;letpop_iftf=matchtoptwith|None->None|Somev->iffvthenpoptelseNone;;letfoldt~init~f=letrecloopaccto_visit=matchto_visitwith|[]->acc|{value;children}::rest->letacc=faccvalueinletto_visit=List.unordered_appendchildrenrestinloopaccto_visitinmatcht.heapwith|None->init|Somenode->loopinit[node];;letlengtht=t.lengthmoduleC=Container.Make(structtypenonrec'at='atletfold=foldletiter=`Define_using_foldletlength=`Customlengthend)letis_emptyt=Option.is_nonet.heapletiter=C.iterletmem=C.memletmin_elt=C.min_eltletmax_elt=C.max_eltletfind=C.findletfind_map=C.find_mapletfor_all=C.for_allletexists=C.existsletsum=C.sumletcount=C.countletto_list=C.to_listletfold_result=C.fold_resultletfold_until=C.fold_until(* We could avoid the intermediate list here, but it doesn't seem like a big deal. *)letto_array=C.to_arrayletof_foldc~comparefold=leth=create~compareinfoldc~init:h~f:add;;letof_listl~compare=of_foldl~compareList.foldletof_arrayarr~compare=of_foldarr~compareArray.foldletsexp_of_tsexp_of_at=List.sexp_of_tsexp_of_a(to_listt)letto_sequencet=Sequence.unfold~init:t~f:pop