Created
July 5, 2025 03:21
-
-
Save kayvank/1b95f96220d5ecdeb91d4522326403f4 to your computer and use it in GitHub Desktop.
Haskell, nixOS script to bubble sort using ST monad,
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env nix-shell | |
| #!nix-shell --pure -p "haskellPackages.ghcWithPackages(pkgs:[pkgs.text pkgs.bytestring pkgs.array pkgs.containers pkgs.mtl])" -i runghc | |
| -- \| | |
| -- bubble sort array using ST monad | |
| {-# LANGUAGE LambdaCase #-} | |
| import Control.Monad | |
| import Control.Monad.ST | |
| import Data.Array.IArray | |
| import Data.IntMap.Strict | |
| import Data.STRef (STRef, modifySTRef, newSTRef, readSTRef, writeSTRef) | |
| until_ :: (Monad m) => m a -> m Bool -> m () | |
| until_ action predicateM = do | |
| action >> predicateM >>= \case | |
| True -> until_ action predicateM | |
| False -> pure () | |
| testUntil_ :: IO Bool | |
| testUntil_ = | |
| readLn | |
| >>= ( \l -> | |
| if l == "stop" | |
| then return False | |
| else return True | |
| ) | |
| bsort :: (Ord a) => [a] -> ST s [a] | |
| bsort list = do | |
| (dict :: IntMap (STRef s a)) <- fromList <$> (zip [0 ..] <$> mapM newSTRef list) | |
| refLast <- newSTRef $ (size dict - 2) | |
| swapState <- newSTRef False | |
| until_ (bubble swapState refLast dict) (isSortCompleted swapState refLast) | |
| traverse readSTRef (Data.IntMap.Strict.elems dict) | |
| where | |
| bubble :: (Ord a) => STRef s Bool -> STRef s Int -> IntMap (STRef s a) -> ST s () | |
| bubble swapState refLast dict = do | |
| lastNdx <- readSTRef refLast | |
| writeSTRef swapState False | |
| forM_ [0 .. lastNdx] $ \i -> do | |
| let e = findWithDefault (error "no index") i dict | |
| e' = findWithDefault (error ("no index: " <> show (i + 1))) (i + 1) dict | |
| xchgSTRefsWhen (\x y -> x > y) e e' swapState | |
| modifySTRef refLast (flip (-) 1) | |
| isSortCompleted | |
| :: (STRef s Bool) | |
| -> (STRef s Int) | |
| -> ST s (Bool) | |
| isSortCompleted swapState lastRef = do | |
| ndx <- readSTRef lastRef | |
| isSwap <- readSTRef swapState | |
| if ndx == -1 || not isSwap | |
| then pure False | |
| else pure True | |
| xchgSTRefsWhen :: (a -> a -> Bool) -> (STRef s a) -> (STRef s a) -> (STRef s Bool) -> ST s () | |
| xchgSTRefsWhen predicate stref stref' swapState = do | |
| a <- readSTRef stref | |
| a' <- readSTRef stref' | |
| case predicate a a' of | |
| True -> writeSTRef stref a' >> writeSTRef stref' a >> writeSTRef swapState True | |
| False -> writeSTRef swapState False | |
| main :: IO () | |
| main = print $ runST $ bsort [10, 9, 8, 7, 0, 4, 5, 3, 1, 2] |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
usage:
should print: