123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899type+'at=|T0|T1of'a*'at'|T2of'a*'a*'at'|T3of'a*'a*'a*'at'|T4of'a*'a*'a*'a*'at'and+'at'=('a*'a*'a*'a)tletempty=T0letreccons:typea.a->at->at=funa0at->matchatwith|T0->T1(a0,T0)|T1(a1,at')->T2(a0,a1,at')|T2(a1,a2,at')->T3(a0,a1,a2,at')|T3(a1,a2,a3,at')->T4(a0,a1,a2,a3,at')|T4(a1,a2,a3,a4,at')->T1(a0,cons(a1,a2,a3,a4)at')letrecget:typea.int->at->a=funnat->matchn,atwith|_,T0->raiseNot_found|0,(T1(a0,_)|T2(a0,_,_)|T3(a0,_,_,_)|T4(a0,_,_,_,_))->a0|1,(T2(_,a1,_)|T3(_,a1,_,_)|T4(_,a1,_,_,_))->a1|2,(T3(_,_,a2,_)|T4(_,_,a2,_,_))->a2|3,(T4(_,_,_,a3,_))->a3|n,(T1(_,at))->get'(n-1)at|n,(T2(_,_,at))->get'(n-2)at|n,(T3(_,_,_,at))->get'(n-3)at|n,(T4(_,_,_,_,at))->get'(n-4)atandget':typea.int->at'->a=funnat->letn'=nlsr2inlet(a0,a1,a2,a3)=getn'atinmatchnland3with|0->a0|1->a1|2->a2|_->a3letrecupdate:typea.at->int->(a->a)->at=funatnu->matchn,atwith|_,T0->raiseNot_found|0,T1(a0,at)->T1(ua0,at)|0,T2(a0,a1,at)->T2(ua0,a1,at)|0,T3(a0,a1,a2,at)->T3(ua0,a1,a2,at)|0,T4(a0,a1,a2,a3,at)->T4(ua0,a1,a2,a3,at)|1,T2(a0,a1,at)->T2(a0,ua1,at)|1,T3(a0,a1,a2,at)->T3(a0,ua1,a2,at)|1,T4(a0,a1,a2,a3,at)->T4(a0,ua1,a2,a3,at)|2,T3(a0,a1,a2,at)->T3(a0,a1,ua2,at)|2,T4(a0,a1,a2,a3,at)->T4(a0,a1,ua2,a3,at)|3,T4(a0,a1,a2,a3,at)->T4(a0,a1,a2,ua3,at)|n,T1(a0,at)->T1(a0,update'at(n-1)u)|n,T2(a0,a1,at)->T2(a0,a1,update'at(n-2)u)|n,T3(a0,a1,a2,at)->T3(a0,a1,a2,update'at(n-3)u)|n,T4(a0,a1,a2,a3,at)->T4(a0,a1,a2,a3,update'at(n-4)u)andupdate':typea.at'->int->(a->a)->at'=funatnu->letn'=nlsr2inletu=matchnland3with|0->(fun(a0,a1,a2,a3)->(ua0,a1,a2,a3))|1->(fun(a0,a1,a2,a3)->(a0,ua1,a2,a3))|2->(fun(a0,a1,a2,a3)->(a0,a1,ua2,a3))|_->(fun(a0,a1,a2,a3)->(a0,a1,a2,ua3))inupdateatn'uletsetnxt=updatetn(fun_->x)letreclength:typea.at->int=funat->matchatwith|T0->0|T1(_,at)->1+4*lengthat|T2(_,_,at)->2+4*lengthat|T3(_,_,_,at)->3+4*lengthat|T4(_,_,_,_,at)->4+4*lengthat(* minimal bench, adding elements:
let () =
let i = int_of_string Sys.argv.(1) in
let j = int_of_string Sys.argv.(2) in
let time = Sys.time () in
for j = 1 to j do
let v = ref T0 in
for i = 1 to i do
v := add i !v
done
done;
let time = Sys.time () -. time in
Printf.printf "adding %d elements %d times took %.03fs (%.03fs per pass)\n"
i j time (time /. float j)
*)