12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091open!CoreopenBonsai.Let_syntaxmoduleId=Inttype'at={contents:'aId.Map.t;append:unitUi_effect.t;set_length:int->unitUi_effect.t;remove:Id.t->unitUi_effect.t}moduleModel=structtypet={data:unitId.Map.t;count:int}[@@derivingfields,equal,sexp]letdefault={data=Int.Map.empty;count=0}letadd_onemodel=letkey=model.countin{data=Map.add_exnmodel.data~key~data:();count=key+1};;letremovemodel~key={modelwithdata=Map.removemodel.datakey}endmoduleAction=structtypet=|Addof{how_many:int}|Removeofint[@@derivingsexp_of]endletstate_componenthere=Bonsai.state_machine0here(moduleModel)(moduleAction)~default_model:Model.default~apply_action:(fun~inject:_~schedule_event:_(model:Model.t)->function|Add{how_many}->Fn.apply_n_times~n:how_manyModel.add_onemodel|Removekey->Model.removemodel~key);;letcomponent'heret~wrap_remove=let%sub{Model.data;count=_},inject_action=state_componenthereinlet%submap=Bonsai.assoc(moduleInt)data~f:(funkey_data->(* Model-resetter allows assoc to reclaim space after a node has been removed *)let%subresult=Bonsai.with_model_resettertinreturn@@let%mapout,reset=resultandkey=keyandinject_action=inject_actioninletinject_remove=Ui_effect.Many[reset;inject_action(Action.Removekey)]inout,inject_remove)inlet%subcontents_map=Bonsai.Incr.computemap~f:(funmap->Incr_map.mapmap~f:(Tuple2.uncurrywrap_remove))inreturn@@let%mapcontents=contents_mapandmap=mapandinject_action=inject_actioninletappend=inject_action(Action.Add{how_many=1})inletremoveid=inject_action(Action.Removeid)inletset_lengthlength=letdifference=length-Map.lengthmapinmatchInt.signdifferencewith|Zero->Ui_effect.Ignore|Pos->inject_action(Action.Add{how_many=difference})|Neg->map|>Map.data|>List.rev_map~f:Tuple2.get2|>Fn.flipList.take(-difference)|>Ui_effect.Manyin{contents;append;set_length;remove};;letcomponentheret=component'heret~wrap_remove:(funa_->a)