{-# LANGUAGE RankNTypes #-}{-# LANGUAGE Safe #-}--------------------------------------------------------------------------------moduleData.Bitonic(Sortable,SortableTrust,sort)where--------------------------------------------------------------------------------importData.Bits(countLeadingZeros,finiteBitSize,shiftL,shiftR,(.&.))importqualifiedForeign.Marshal.AllocasFFIimportForeign.Ptr(Ptr,plusPtr)importForeign.Storable(Storable)importqualifiedForeign.StorableasFFI---------------------------------------------------------------------------------- To prevent the users from adding instances of `ForeignMemoryInterface`, we-- provide a middle-layer (`FMEMI`) between the `Monad` instance and the `Proxy`-- (`ForeignMemoryInterface`) instance.---- Note: This is redundant as by using `RankNTypes` to create a type alias and-- expose that type from the module instead.classMonadm=>FMEMImclassFMEMIm=>ForeignMemoryInterfacemwheremalloc::Storablea=>Int->m(Ptra)free::Storablea=>Ptra->m( )peek::Storablea=>Ptra->Int->mapoke::Storablea=>Ptra->Int->a->m( )--------------------------------------------------------------------------------typeSortableaio=(Storablea,Orda,ForeignMemoryInterfaceio)=>[a]->io[a]typeSortableTrusta=(Storablea,Orda)=>[a]->[a]typeOffSet=InttypeLength=Int--------------------------------------------------------------------------------instanceFMEMIIOinstanceForeignMemoryInterfaceIOwheremalloc=FFI.mallocBytesfree=FFI.freepeek=FFI.peekElemOffpoke=FFI.pokeElemOff--------------------------------------------------------------------------------sort::Sortableaiosort[ ]=pure[]sortxs@(hd:_)=mallocm>>=\p->storep0ys>>=\_->-- initiate memory values to the list max valuestorep0xs>>=\_->sorterpon>>=\_->querypn>>=\zs->freep>>=\_->pure$takelzswherel=lengthxsn=pow2l-- Ensure that allocated memory is 2^io=FFI.sizeOfhdm=n*oys=taken$cycle[foldl1maxxs]--------------------------------------------------------------------------------query::(Storablea,ForeignMemoryInterfaceio)=>Ptra->Length->io[a]querypn=aux0whereauxi|i<n=aux(i+1)>>=\tl->peekpi>>=\hd->pure$hd:tl|otherwise=pure[]store::(Storablea,ForeignMemoryInterfaceio)=>Ptra->OffSet->[a]->io()store__[ ]=pure()storepi(x:xs)=pokepix>>storep(i+1)xs--------------------------------------------------------------------------------pow2::Int->Intpow2x=ifx.&.(x-1)==0thenxelse1`shiftL`(b-z)whereb=finiteBitSizexz=countLeadingZerosxwait::Applicativef=>t->a->fawaitxy=pure$x`seq`ynext::(Storablea)=>Ptra->OffSet->Ptranextpo=p`plusPtr`(1*o)`asTypeOf`pprev::(Storablea)=>Ptra->OffSet->Ptraprevpo=p`plusPtr`(-1*o)`asTypeOf`p--------------------------------------------------------------------------------sorter::(Storablea,Orda,ForeignMemoryInterfaceio)=>Ptra->OffSet->Length->io()sorterpon=(if2<nthensorterpom>>=\f->sorterqom>>=\s->f`wait`selsepure())>>=\_->mergerponwherem=n`shiftR`1q=p`plusPtr`(m*o)`asTypeOf`pmerger::(Storablea,Orda,ForeignMemoryInterfaceio)=>Ptra->OffSet->Length->io()mergerpon=wp(prevlo)>>=\_->if2<nthenbitonicpom>>=\f->bitonicqom>>=\s->f`wait`selsepure()wherem=n`shiftR`1q=p`plusPtr`(m*o)`asTypeOf`pl=p`plusPtr`(n*o)`asTypeOf`pwij|i<q=comparatorij>>w(nextio)(prevjo)|otherwise=pure()comparator::(Storablea,Orda,ForeignMemoryInterfaceio)=>Ptra->Ptra->io()comparatorpq=peekp0>>=\i->peekq0>>=\j->pokep0(minij)>>=\f->pokeq0(maxij)>>=\s->f`wait`sbitonic::(Storablea,Orda,ForeignMemoryInterfaceio)=>Ptra->OffSet->Length->io()bitonicpon=cleanerpon>>=\_->if2<nthenbitonicpom>>=\f->bitonicqom>>=\s->f`wait`selsepure()wherem=n`shiftR`1q=p`plusPtr`(m*o)`asTypeOf`pcleaner::(Storablea,Orda,ForeignMemoryInterfaceio)=>Ptra->OffSet->Length->io()cleanerpon=wpqwherem=n`shiftR`1q=p`plusPtr`(m*o)`asTypeOf`pwij|i<q=comparatorij>>w(nextio)(nextjo)|otherwise=pure()
#!/usr/bin/envstack{- stack
--resolver lts-12.0
--install-ghc
script
--ghc-options -Werror
--ghc-options -Wall
--
-}{-# LANGUAGE Trustworthy #-}--------------------------------------------------------------------------------moduleMain(main)where--------------------------------------------------------------------------------importSystem.IO.Unsafe(unsafePerformIO)importData.Bitonic(SortableTrust,sort)---------------------------------------------------------------------------------- In case you need the sorting algorithm to produce no IO effects, you will-- have to create your own local version by implementing the `SortableTrust`-- alias type with `unsafePerformIO`.trust::SortableTrustatrust=unsafePerformIO.sort--------------------------------------------------------------------------------main::IO()main=doputStrLn$"# Bitonic sort"putStrLn$"> xs (initial): "++(showxs)sortxs>>=putStrLn.("> ys (effects): "++).showputStrLn$"> zs (trusted): "++(show$trustxs)wherexs=reverse[0..15]::[Word]