module Utils where
import IOExts
import MArray
import Monad(ap,when,liftM2,liftM)
import Maybe(listToMaybe)
import Random
import List(partition,groupBy,sortBy)
import Concurrent
infixl 1 #, <#
type Mutable = IORef
new = newIORef
readRef = readIORef
writeRef = writeIORef
f # m = fmap f m
mf <# mx = mf `ap` mx
findM p [] = return Nothing
findM p (x:xs) = do
b <- p x
if b then return (Just x) else findM p xs
swap (x,y) = (y,x)
collectBySnd x =
map pick .
groupBy eqSnd .
sortBy cmpSnd $ x
where
pick xys@((_,y):_) = ({-sort $-} map fst xys,y)
pick _ = error "groupBy bug: it returned an []"
collectByFst x = map swap . collectBySnd . map swap $ x
onSnd f (_,y1) (_,y2) = f y1 y2
cmpSnd x = onSnd compare x
eqSnd x = onSnd (==) x
findFilter :: (a -> Bool) -> [a] -> Maybe (a,[a])
findFilter p [] = Nothing
findFilter p (x:xs)
| p x = return (x,xs)
| otherwise = do
(y,ys) <- findFilter p xs
return (y,x:ys)
f `apSnd` (x,y) = (x,f y)
instance (Num a, Num b) => Num (a,b) where
(x,y) + (a,b) = (x + a, y + b)
(x,y) * (a,b) = (x * a, y * b)
negate (x,y) = (-x,-y)
signum (x,y) = (signum x, signum y)
abs (x,y) = (abs x, abs y)
fromInteger x = undefined
parse :: Read a => String -> Maybe a
parse = listToMaybe . map fst . reads
compareBy f x y = compare (f x) (f y)
partitionM p [] = return ([],[])
partitionM p (x:xs) = do b <- p x
(ys,ns) <- partitionM p xs
return $
if b then (x:ys,ns) else (ys,x:ns)
whenM :: Monad m => m Bool -> m () -> m ()
whenM p m = do b <- p
if b then m else return ()
unlessM :: Monad m => m Bool -> m () -> m ()
unlessM = whenM . notM
while :: Monad m => m Bool -> m () -> m ()
while p m = whenM p (m >> while p m)
m `untilM` p = m >> unlessM p (m `untilM` p)
repeatM m = whenM m (repeatM m)
ifM p t e = do b <- p
if b then t else e
andM :: Monad m => m Bool -> m Bool -> m Bool
andM p q = ifM p q (return False)
notM p = liftM not p
updArray a p f = writeArray a p . f =<< readArray a p
partitionFst xs = let (as,bs) = partition fst xs in (map snd as, map snd bs)
o `get` f = readRef (f o)
(o `set` f) x = writeRef (f o) x
(o `upd` f) g = let r = f o in writeRef r . g =<< readRef r
spacesTo_ = foldr f ""
where
f ' ' xs = '_' : xs
f x xs = x : xs
instance (Random a, Random b) => Random (a,b) where
random g = let (x,g1) = random g
(y,g2) = random g1
in ((x,y),g2)
randomR ((x1,y1),(x2,y2)) g =
let (x,g1) = randomR (x1,x2) g
(y,g2) = randomR (y1,y2) g1
in ((x,y),g2)
prt msg = prt ("# " ++ msg)
-- take from channel
-- bool indicates if we should wait if not enough are pressent
takeC chan _ 0 = return []
takeC chan wait n =
do empty <- isEmptyChan chan
if empty && not wait
then return []
else do p <- readChan chan
ps <- takeC chan wait (n-1)
return (p:ps)
allM p [] = return True
allM p (m:ms) = p m `andM` allM p ms
linesBy :: (a -> Bool) -> [a] -> [[a]]
linesBy p [] = []
linesBy p s = let (l,s') = break p s
in l : case s' of
[] -> []
(_:s'') -> linesBy p s''