------------------------------------------------------------------------------------- -- | -- Copyright : (c) Hans Hoglund 2012 -- -- License : GPL -- -- Maintainer : hans@hanshoglund.se -- Stability : stable -- Portability : portable -- -- Utility functions. -- ------------------------------------------------------------------------------------- module Control.Reactive.Util ( -- ** String and Char toUpperChar, toLowerChar, toUpperString, toLowerString, toCapitalString, isSubstringOf, isInfixOfNormalized, isSubstringOfNormalized, -- ** Lists prefix, suffix, sep, pre, post, wrap, concatSep, concatPre, concatPost, concatWrap, concatLines, divideList, breakList, -- ** Monads concatMapN, concatMapM, concatMapA, -- ** Special map mapIndexed, -- ** Mathematics tau, -- ** System -- execute, ) where import Prelude hiding (concat) import Data.Monoid import Control.Applicative import Data.Foldable import Data.Traversable import Control.Monad (MonadPlus) -- import System.Posix import qualified Data.Char as Char import qualified Data.List as List ------------------------------------------------------------------------------------- -- String and Char ------------------------------------------------------------------------------------- -- | -- Synonym for 'Char.toUpper' toUpperChar :: Char -> Char toUpperChar = Char.toUpper -- | -- Synonym for 'Char.toLower' toLowerChar :: Char -> Char toLowerChar = Char.toLower -- | -- Synonym for 'fmap Char.toUpper' toUpperString :: String -> String toUpperString = fmap Char.toUpper -- | -- Synonym for 'fmap Char.toLower' toLowerString :: String -> String toLowerString = fmap Char.toLower -- | -- Convert a string to use upper case for the leading letter and lower case for -- remaining letters. toCapitalString :: String -> String toCapitalString [] = [] toCapitalString (x:xs) = toUpperChar x : toLowerString xs isSubstringOf :: String -> String -> Bool a `isSubstringOf` b = a `List.isPrefixOf` b || a `List.isInfixOf` b || a `List.isSuffixOf` b isInfixOfNormalized :: String -> String -> Bool a `isInfixOfNormalized` b = toLowerString a `List.isInfixOf` toLowerString b isSubstringOfNormalized :: String -> String -> Bool a `isSubstringOfNormalized` b = toLowerString a `isSubstringOf` toLowerString b ------------------------------------------------------------------------------------- -- List ------------------------------------------------------------------------------------- -- | -- Synonym for '(++)' -- prefix :: [a] -> [a] -> [a] prefix x = (x ++) -- | -- Synonym for 'flip (++)' -- suffix :: [a] -> [a] -> [a] suffix x = (++ x) -- | -- Separate a list by the given element. -- -- Equivalent to 'List.intersperse' -- sep :: a -> [a] -> [a] sep = List.intersperse -- | -- Initiate and separate a list by the given element. -- pre :: a -> [a] -> [a] pre x = (x :) . sep x -- | -- Separate and terminate a list by the given element. -- post :: a -> [a] -> [a] post x = suffix [x] . sep x -- | -- Separate and terminate a list by the given element. -- wrap :: a -> a -> [a] -> [a] wrap x y = (x :) . suffix [y] . sep x -- | -- Combination of 'concat' and 'sep'. -- concatSep :: [a] -> [[a]] -> [a] concatSep x = concat . sep x -- | -- Combination of 'concat' and 'pre'. -- concatPre :: [a] -> [[a]] -> [a] concatPre x = concat . pre x -- | -- Combination of 'concat' and 'post'. -- concatPost :: [a] -> [[a]] -> [a] concatPost x = concat . post x -- | -- Combination of 'concat' and 'wrap'. -- concatWrap :: [a] -> [a] -> [[a]] -> [a] concatWrap x y = concat . wrap x y concatLines :: [String] -> String concatLines = concatPost "\n" -- | -- Divide a list into parts of maximum length n. -- divideList :: Int -> [a] -> [[a]] divideList n xs | length xs <= n = [xs] | otherwise = [take n xs] ++ (divideList n $ drop n xs) -- | -- Break up a list into parts of maximum length n, inserting the given list as separator. -- Useful for breaking up strings, as in @breakList 80 "\n" str@. -- breakList :: Int -> [a] -> [a] -> [a] breakList n z = mconcat . List.intersperse z . divideList n -- | -- A version of 'concatMap' generalized to arbitrary 'Monoid' instances. -- concatMapN :: (Applicative f, Monoid b) => (a -> f b) -> [a] -> f b concatMapN f = fmap mconcat . traverse f -- | -- A version of 'concatMap' generalized to arbitrary 'MonadPlus' instances. -- concatMapM :: (MonadPlus m, Applicative f, Traversable t) => (a -> f (m b)) -> t a -> f (m b) concatMapM f = fmap msum . traverse f -- | -- A version of 'concatMap' generalized to arbitrary 'Alternative' instances. -- concatMapA :: (Alternative m, Applicative f, Traversable t) => (a -> f (m b)) -> t a -> f (m b) concatMapA f = fmap asum . traverse f mapIndexed :: (Int -> a -> b) -> [a] -> [b] mapIndexed f as = map (uncurry f) (zip is as) where n = length as - 1 is = [0..n] tau :: Floating a => a tau = 2 * pi {- -- | -- Excecute an external process asynchronously (using @forkProcess@) with the given arguments. -- execute :: FilePath -> [String] -> IO () execute program args = do forkProcess $ executeFile program True args Nothing return () -}