1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889openTypesopenTypecheckopenComplextypelowest_found=FInt|FFloat|FComplexletrecfind_lowest_kindlowls=matchlswith|[]->low|(EvtComplex_)::_->FComplex|(EvtInt_)::xs->find_lowest_kindlowxs|(EvtFloat_)::xs->find_lowest_kindFFloatxs|(_)::_->raise(TypeError"value is not a number in arithmetical operator")letnumLowerlowertonum=matchlowertowith|FInt->num|FFloat->(matchnumwith|EvtIntx->EvtFloat(float_of_intx)|EvtFloatx->EvtFloatx|EvtComplexx->EvtComplexx|_->raise(TypeError"not a number"))|FComplex->(matchnumwith|EvtIntx->EvtComplex{re=float_of_intx;im=0.}|EvtFloatx->EvtComplex{re=x;im=0.}|EvtComplexx->EvtComplexx|_->raise(TypeError"not a number"))(** Accept a list of numbers and flatten out their
kind on the numerical tower hierarchy *)letflattenNumListl=letfound=find_lowest_kindFIntlin(found,List.map(numLowerfound)l)letrecunpackIntListl=matchlwith|[]->[]|(EvtIntx)::xs->x::(unpackIntListxs)|_::_->raise(TypeError"internal type error")letrecunpackFloatListl=matchlwith|[]->[]|(EvtFloatx)::xs->x::(unpackFloatListxs)|_::_->raise(TypeError"internal type error")letrecunpackComplexListl=matchlwith|[]->[]|(EvtComplexx)::xs->x::(unpackComplexListxs)|_::_->raise(TypeError"internal type error")letaddargs=letfound,numlist=flattenNumListargsinmatchfoundwith|FInt->EvtInt(List.fold_left(+)0(unpackIntListnumlist))|FFloat->EvtFloat(List.fold_left(+.)0.(unpackFloatListnumlist))|FComplex->EvtComplex(List.fold_left(Complex.add)Complex.zero(unpackComplexListnumlist))letmultargs=letfound,numlist=flattenNumListargsinmatchfoundwith|FInt->EvtInt(List.fold_left(*)1(unpackIntListnumlist))|FFloat->EvtFloat(List.fold_left(*.)1.(unpackFloatListnumlist))|FComplex->EvtComplex(List.fold_left(Complex.mul){re=1.;im=1.}(unpackComplexListnumlist))letsubargs=letfound,numlist=flattenNumListargsinletx,y=(matchnumlistwith|[x;y]->(x,y)|_->raise(WrongPrimitiveArgs))inmatchfoundwith|FInt->EvtInt(unpack_intx-unpack_inty)|FFloat->EvtFloat(unpack_floatx-.unpack_floaty)|FComplex->EvtComplex(Complex.sub(unpack_complexx)(unpack_complexy))letdivargs=letfound,numlist=flattenNumListargsinletx,y=(matchnumlistwith|[x;y]->(x,y)|_->raise(WrongPrimitiveArgs))inmatchfoundwith|FInt->EvtInt(unpack_intx/unpack_inty)|FFloat->EvtFloat(unpack_floatx/.unpack_floaty)|FComplex->EvtComplex(Complex.div(unpack_complexx)(unpack_complexy))lettable=[("flatnum",((funx->flattenNumListx|>snd|>funy->EvtListy),0));("add",(add,0));("sub",(sub,2));("div",(div,0));("mult",(mult,0))]