--- ---------------------------------------------------------------------------- --- This module provides some utility operations. --- --- @author Jan Tikovsky --- @version January 2018 --- ---------------------------------------------------------------------------- module Utils where import Directory (getCurrentDirectory, setCurrentDirectory) import Data.FiniteMap import Text.Pretty -- some useful combinators for monads infixl 4 <$>, <*> -- TODO: Remove when there are corresponding functions in the libraries zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m () zipWithM_ f xs ys = sequence_ $ zipWith f xs ys --- Apply a pure function to the result of a monadic action. (<$>) :: Monad m => (a -> b) -> m a -> m b (<$>) f act = act >>= \x -> return (f x) --- Apply a function originating from the first monadic computation --- to the result of the second monadic action. (<*>) :: Monad m => m (a -> b) -> m a -> m b a <*> b = a >>= \f -> b >>= \x -> return (f x) --- Pad a string to a specific length with space from the right side. rpad :: Int -> String -> String rpad n str = str ++ replicate (n - length str) ' ' --- swap the components of a tuple swap :: (a, b) -> (b, a) swap (x, y) = (y, x) --- zip three lists zip3 :: [a] -> [b] -> [c] -> [(a, b, c)] zip3 xs ys zs = case xs of [] -> [] a:as -> case ys of [] -> [] b:bs -> case zs of [] -> [] c:cs -> (a, b, c) : zip3 as bs cs --- Pretty print finite map ppFM :: ((a, b) -> Doc) -> FM a b -> Doc ppFM ppEntry fm = listSpaced $ map ppEntry $ fmToList fm --- Perform an IO action in the given directory and return to the previous --- directory afterwards inDirectory :: String -> IO a -> IO a inDirectory dir action = do prevDir <- getCurrentDirectory setCurrentDirectory dir r <- action setCurrentDirectory prevDir return r -- ----------------------------------------------------------------------------- -- Tuple utilities -- ----------------------------------------------------------------------------- -- Apply given function to first component of a tuple mapFst :: (a -> b) -> (a, c) -> (b, c) mapFst f (x, y) = (f x, y) -- Apply given function to second component of a tuple mapSnd :: (a -> b) -> (c, a) -> (c, b) mapSnd f (x, y) = (x, f y) fst3 :: (a, b, c) -> a fst3 (x, _, _) = x snd3 :: (a, b, c) -> b snd3 (_, y, _) = y trd3 :: (a, b, c) -> c trd3 (_, _, z) = z trTpl3 :: (a -> b) -> (c -> d) -> (e -> f) -> (a, c, e) -> (b, d, f) trTpl3 f g h (x, y, z) = (f x, g y, h z) -- TODO: Remove when there is a functor instance for Maybe instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just x) = Just (f x)