12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455(*---------------------------------------------------------------------------
Copyright (c) 2025 The more programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)includeListletcons_ifbvvs=ifbthenv::vselsevsletclassify(typea)(typeb)?(cmp_elts:a->a->int=Stdlib.compare)?(cmp_classes:b->b->int=Stdlib.compare)~classes:(classes:(a->blist))els=letmoduleSet=Set.Make(structtypet=aletcompare=cmp_eltsend)inletmoduleMap=Map.Make(structtypet=bletcompare=cmp_classesend)inletadd_classesaccp=letadd_classaccc=tryMap.addc(Set.addp(Map.findcacc))accwith|Not_found->Map.addc(Set.singletonp)accinList.fold_leftadd_classacc(classesp)inletclasses=List.fold_leftadd_classesMap.emptyelsinList.rev(Map.fold(funcelsacc->(c,Set.elementsels)::acc)classes[])letdistinct(typea)(compare:a->a->int)vs=letmoduleSet=Set.Make(structtypet=aletcompare=compareend)inletrecloopseenacc=function|[]->List.revacc|v::vs->ifSet.memvseenthenloopseenaccvselseloop(Set.addvseen)(v::acc)vsinloopSet.empty[]vsletrecfold_stop_on_errorflacc=matchlwith|[]->Okacc|v::vs->matchfvaccwith|Okacc->fold_stop_on_errorfvsacc|Error_ase->eletreciter_stop_on_errorf=function|[]->Ok()|v::vs->matchfvwith|Error_ase->e|Okv->iter_stop_on_errorfvsletreciter_iter_on_error~errorf=function|[]->()|v::vs->(matchfvwithError_ase->errore|Ok_->());iter_iter_on_error~errorfvs