reenact-0.6: src/Control/Reactive/Util.hs
-------------------------------------------------------------------------------------
-- |
-- 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 ()
-}