I tried to implement the bitonicsorter I wrote about in my masters thesis. The
result is the following code:

//BitonicSort////http://www.diku.dk/forskning/performance-engineering/Ramon/thesis.pdfletinlineisPow2x=matchxwith|0->false|_->x&&&(x-1)=0letcomparatorxy=matchxwith|_whenx<y->(x,y)|_->(y,x)lethalfCleanerbs=letn=bs|>Array.lengthletm=n/2matchisPow2(n)with|true->()|false->failwith"Input array %A, must be n=2^k"bsArray.mapi(funix->matchiwith|_wheni<m->fst(comparatorxbs.[m+i])|_->snd(comparatorxbs.[i-m]))bsletrecbitonicSorterbs=letn=bs|>Array.lengthletm=n/2matchisPow2(n)with|true->()|false->failwith"Input array %A, must be n=2^k"bsletbs'=halfCleanerbsletbs1=bs'.[0..(m-1)]letbs2=bs'.[m..(n-1)]matchnwith|_when2<n->Array.append(bitonicSorterbs1)(bitonicSorterbs2)|_->bs'letmergerss1ss2=letm1=ss1|>Array.lengthletm2=ss2|>Array.lengthletn=m1+m2letm=n/2match(m1=m2)with|true->()|false->failwith"Input arrays (%A,%A), must have the same length"ss1ss2matchisPow2(n)with|true->()|false->failwith"Comibnation of (%A,%A) arrays, must be n=2^k"ss1ss2letss2'=ss2|>Array.revletss1''=Array.map2(funxy->fst(comparatorxy))ss1ss2'letss2''=Array.map2(funxy->snd(comparatorxy))ss1ss2'matchnwith|_when2<n->Array.append(bitonicSorterss1'')(bitonicSorterss2'')|_->Array.appendss1''ss2''letrecsorterarray=letn=array|>Array.lengthletm=n/2matchisPow2(n)with|true->()|false->failwith"Input array %A, must be n=2^k"arrayletas1=array.[0..(m-1)]letas2=array.[m..(n-1)]matchnwith|_when2<n->merger(sorteras1)(sorteras2)|_->mergeras1as2letn=1<<<16leta=Array.initn(funi->i%2)sortera

It still lacks of speed, even with the use of the included libraries
Array.Parallel or Async.Parallel /
Async.RunSynchronously (fork/join) but it was fun to write as
usual.

REMARK: It’s much more readable than the code I wrote back in the days …