12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485open!BaseincludeObserver0letunmapt~f=create(funx~size~hash->observet(fx)~size~hash)letof_hash_foldf=create(funx~size:_~hash->fhashx)letfixed_pointwrap=letrecfx~size~hash=observe(wrap(createf))x~size~hashincreatef;;letunit=opaqueletbool=of_hash_foldBool.hash_fold_tletchar=of_hash_foldChar.hash_fold_tletint=of_hash_foldInt.hash_fold_tletint32=of_hash_foldInt32.hash_fold_tletint63=of_hash_foldInt63.hash_fold_tletint64=of_hash_foldInt64.hash_fold_tletnativeint=of_hash_foldNativeint.hash_fold_tletfloat=of_hash_foldFloat.hash_fold_tletstring=of_hash_foldString.hash_fold_tletsexp=of_hash_foldSexp.hash_fold_tleteitherfst_tsnd_t=create(funeither~size~hash->match(either:_Either.t)with|Firstfst->observefst_tfst~size~hash:(hash_fold_inthash1)|Secondsnd->observesnd_tsnd~size~hash:(hash_fold_inthash2));;letresultok_terr_t=unmap(eitherok_terr_t)~f:(function|Okok->Firstok|Errorerr->Seconderr);;letbothfst_tsnd_t=create(fun(fst,snd)~size~hash->lethash=observefst_tfst~size~hashinlethash=observesnd_tsnd~size~hashinhash);;letoptionvalue_t=unmap(eitheropaquevalue_t)~f:(function|None->First()|Somevalue->Secondvalue);;letlistelt_t=create(funlist~size~hash->letrandom=Splittable_random.State.of_int(Hash.get_hash_valuehash)inletlength=List.lengthlistinletsizes=Generator.sizes~min_length:length~max_length:length()|>Generator.generate~size~randominList.fold2_exnlistsizes~init:(hash_fold_inthash0)~f:(funhasheltsize->observeelt_telt~size~hash:(hash_fold_inthash1)));;letfndomrng=create(funf~size~hash->letrandom=Splittable_random.State.of_int(Hash.get_hash_valuehash)inletsizes=(* Empirically, doubling the size when generating the list of inputs gives us much
better coverage of the space of functions. *)Generator.generate(Generator.sizes())~size:(size*2)~randominList.foldsizes~init:hash~f:(funhashsize->letx=Generator.generatedom~size~randominobserverng(fx)~size~hash));;letmap_treekey_obsdata_obs=unmap(list(bothkey_obsdata_obs))~f:Map.Using_comparator.Tree.to_alist;;letset_treeelt_obs=unmap(listelt_obs)~f:Set.Using_comparator.Tree.to_listletmap_tkey_obsdata_obs=unmap(map_treekey_obsdata_obs)~f:Map.Using_comparator.to_tree;;letset_telt_obs=unmap(set_treeelt_obs)~f:Set.Using_comparator.to_tree