-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Extra functions I use. -- -- A library of extra functions for the standard Haskell libraries. Most -- functions are simple additions, filling out missing functionality. A -- few functions are available in later versions of GHC, but this package -- makes them available back to GHC 7.2. -- -- The module Extra documents all functions provided by this -- library. Modules such as Data.List.Extra provide extra -- functions over Data.List and also reexport Data.List. -- Users are recommended to replace Data.List imports with -- Data.List.Extra if they need the extra functionality. @package extra @version 1.7 -- | This module extends Data.IORef with operations forcing the -- value written to the IORef. Some of these functions are available in -- later versions of GHC, but not all. module Data.IORef.Extra -- | Evaluates the value before calling writeIORef. writeIORef' :: IORef a -> a -> IO () -- | Evaluates the value before calling atomicWriteIORef. atomicWriteIORef' :: IORef a -> a -> IO () -- | Variant of atomicModifyIORef which ignores the return value atomicModifyIORef_ :: IORef a -> (a -> a) -> IO () -- | Variant of atomicModifyIORef' which ignores the return value atomicModifyIORef'_ :: IORef a -> (a -> a) -> IO () -- | Extra functions for working with pairs and triples. Some of these -- functions are available in the Control.Arrow module, but here -- are available specialised to pairs. Some operations work on triples. module Data.Tuple.Extra -- | Update the first component of a pair. -- --
-- first succ (1,"test") == (2,"test") --first :: (a -> a') -> (a, b) -> (a', b) -- | Update the second component of a pair. -- --
-- second reverse (1,"test") == (1,"tset") --second :: (b -> b') -> (a, b) -> (a, b') -- | Given two functions, apply one to the first component and one to the -- second. A specialised version of ***. -- --
-- (succ *** reverse) (1,"test") == (2,"tset") --(***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') infixr 3 *** -- | Given two functions, apply both to a single argument to form a pair. A -- specialised version of &&&. -- --
-- (succ &&& pred) 1 == (2,0) --(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) infixr 3 &&& -- | Duplicate a single value into a pair. -- --
-- dupe 12 == (12, 12) --dupe :: a -> (a, a) -- | Apply a single function to both components of a pair. -- --
-- both succ (1,2) == (2,3) --both :: (a -> b) -> (a, a) -> (b, b) -- | Update the first component of a pair. -- --
-- firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")] --firstM :: Functor m => (a -> m a') -> (a, b) -> m (a', b) -- | Update the second component of a pair. -- --
-- secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")] --secondM :: Functor m => (b -> m b') -> (a, b) -> m (a, b') -- | Extract the fst of a triple. fst3 :: (a, b, c) -> a -- | Extract the snd of a triple. snd3 :: (a, b, c) -> b -- | Extract the final element of a triple. thd3 :: (a, b, c) -> c -- | Converts an uncurried function to a curried function. curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d -- | Converts a curried function to a function on a triple. uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d -- | This module extends Data.Typeable with extra functions -- available in later GHC versions. The package also exports the existing -- Data.Typeable functions. -- -- Currently this module has no functionality beyond -- Data.Typeable. module Data.Typeable.Extra -- | Extra numeric functions - formatting and specialised conversions. module Numeric.Extra -- | Show a number to a fixed number of decimal places. -- --
-- showDP 4 pi == "3.1416" -- showDP 0 pi == "3" -- showDP 2 3 == "3.00" --showDP :: RealFloat a => Int -> a -> String -- | Specialised numeric conversion, type restricted version of -- fromIntegral. intToDouble :: Int -> Double -- | Specialised numeric conversion, type restricted version of -- fromIntegral. intToFloat :: Int -> Float -- | Specialised numeric conversion, type restricted version of -- realToFrac. floatToDouble :: Float -> Double -- | Specialised numeric conversion, type restricted version of -- realToFrac. doubleToFloat :: Double -> Float -- | This module extends Data.List with extra functions of a similar -- nature. The package also exports the existing Data.List -- functions. Some of the names and semantics were inspired by the -- text package. module Data.List.Extra -- | Convert a string to lower case. -- --
-- lower "This is A TEST" == "this is a test" -- lower "" == "" --lower :: String -> String -- | Convert a string to upper case. -- --
-- upper "This is A TEST" == "THIS IS A TEST" -- upper "" == "" --upper :: String -> String -- | Remove spaces from either side of a string. A combination of -- trimEnd and trimStart. -- --
-- trim " hello " == "hello" -- trimStart " hello " == "hello " -- trimEnd " hello " == " hello" -- \s -> trim s == trimEnd (trimStart s) --trim :: String -> String -- | Remove spaces from the start of a string, see trim. trimStart :: String -> String -- | Remove spaces from the end of a string, see trim. trimEnd :: String -> String -- | Split the first word off a string. Useful for when starting to parse -- the beginning of a string, but you want to accurately preserve -- whitespace in the rest of the string. -- --
-- word1 "" == ("", "")
-- word1 "keyword rest of string" == ("keyword","rest of string")
-- word1 " keyword\n rest of string" == ("keyword","rest of string")
-- \s -> fst (word1 s) == concat (take 1 $ words s)
-- \s -> words (snd $ word1 s) == drop 1 (words s)
--
word1 :: String -> (String, String)
-- | Split the first line off a string.
--
--
-- line1 "" == ("", "")
-- line1 "test" == ("test","")
-- line1 "test\n" == ("test","")
-- line1 "test\nrest" == ("test","rest")
-- line1 "test\nrest\nmore" == ("test","rest\nmore")
--
line1 :: String -> (String, String)
-- | Escape a string such that it can be inserted into an HTML document or
-- " attribute without any special interpretation. This requires
-- escaping the <, >, & and
-- " characters. Note that it will escape " and
-- ' even though that is not required in an HTML body (but is
-- not harmful).
--
-- -- escapeHTML "this is a test" == "this is a test" -- escapeHTML "<b>\"g&t\"</n>" == "<b>"g&t"</n>" -- escapeHTML "t'was another test" == "t'was another test" --escapeHTML :: String -> String -- | Escape a string so it can form part of a JSON literal. This requires -- escaping the special whitespace and control characters. Additionally, -- Note that it does not add quote characters around the string. -- --
-- escapeJSON "this is a test" == "this is a test" -- escapeJSON "\ttab\nnewline\\" == "\\ttab\\nnewline\\\\" -- escapeJSON "\ESC[0mHello" == "\\u001b[0mHello" --escapeJSON :: String -> String -- | Invert of escapeHTML (does not do general HTML unescaping) -- --
-- \xs -> unescapeHTML (escapeHTML xs) == xs --unescapeHTML :: String -> String -- | General JSON unescaping, inversion of escapeJSON and all other -- JSON escapes. -- --
-- \xs -> unescapeJSON (escapeJSON xs) == xs --unescapeJSON :: String -> String -- | Drop a number of elements from the end of the list. -- --
-- dropEnd 3 "hello" == "he" -- dropEnd 5 "bye" == "" -- dropEnd (-1) "bye" == "bye" -- \i xs -> dropEnd i xs `isPrefixOf` xs -- \i xs -> length (dropEnd i xs) == max 0 (length xs - max 0 i) -- \i -> take 3 (dropEnd 5 [i..]) == take 3 [i..] --dropEnd :: Int -> [a] -> [a] -- | Take a number of elements from the end of the list. -- --
-- takeEnd 3 "hello" == "llo" -- takeEnd 5 "bye" == "bye" -- takeEnd (-1) "bye" == "" -- \i xs -> takeEnd i xs `isSuffixOf` xs -- \i xs -> length (takeEnd i xs) == min (max 0 i) (length xs) --takeEnd :: Int -> [a] -> [a] -- | splitAtEnd n xs returns a split where the second -- element tries to contain n elements. -- --
-- splitAtEnd 3 "hello" == ("he","llo")
-- splitAtEnd 3 "he" == ("", "he")
-- \i xs -> uncurry (++) (splitAt i xs) == xs
-- \i xs -> splitAtEnd i xs == (dropEnd i xs, takeEnd i xs)
--
splitAtEnd :: Int -> [a] -> ([a], [a])
-- | Break, but from the end.
--
--
-- breakEnd isLower "youRE" == ("you","RE")
-- breakEnd isLower "youre" == ("youre","")
-- breakEnd isLower "YOURE" == ("","YOURE")
-- \f xs -> breakEnd (not . f) xs == spanEnd f xs
--
breakEnd :: (a -> Bool) -> [a] -> ([a], [a])
-- | Span, but from the end.
--
--
-- spanEnd isUpper "youRE" == ("you","RE")
-- spanEnd (not . isSpace) "x y z" == ("x y ","z")
-- \f xs -> uncurry (++) (spanEnd f xs) == xs
-- \f xs -> spanEnd f xs == swap (both reverse (span f (reverse xs)))
--
spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
-- | A version of dropWhileEnd but with different strictness
-- properties. The function dropWhileEnd can be used on an
-- infinite list and tests the property on each character. In contrast,
-- dropWhileEnd' is strict in the spine of the list but only tests
-- the trailing suffix. This version usually outperforms
-- dropWhileEnd if the list is short or the test is expensive.
-- Note the tests below cover both the prime and non-prime variants.
--
-- -- dropWhileEnd isSpace "ab cde " == "ab cde" -- dropWhileEnd' isSpace "ab cde " == "ab cde" -- last (dropWhileEnd even [undefined,3]) == undefined -- last (dropWhileEnd' even [undefined,3]) == 3 -- head (dropWhileEnd even (3:undefined)) == 3 -- head (dropWhileEnd' even (3:undefined)) == undefined --dropWhileEnd' :: (a -> Bool) -> [a] -> [a] -- | A version of takeWhile operating from the end. -- --
-- takeWhileEnd even [2,3,4,6] == [4,6] --takeWhileEnd :: (a -> Bool) -> [a] -> [a] -- | Return the prefix of the second list if its suffix matches the entire -- first list. -- -- Examples: -- --
-- stripSuffix "bar" "foobar" == Just "foo" -- stripSuffix "" "baz" == Just "baz" -- stripSuffix "foo" "quux" == Nothing --stripSuffix :: Eq a => [a] -> [a] -> Maybe [a] -- | Return the the string before and after the search string, or -- Nothing if the search string is not present. -- -- Examples: -- --
-- stripInfix "::" "a::b::c" == Just ("a", "b::c")
-- stripInfix "/" "foobar" == Nothing
--
stripInfix :: Eq a => [a] -> [a] -> Maybe ([a], [a])
-- | Similar to stripInfix, but searches from the end of the string.
--
--
-- stripInfixEnd "::" "a::b::c" == Just ("a::b", "c")
--
stripInfixEnd :: Eq a => [a] -> [a] -> Maybe ([a], [a])
-- | Drops the given prefix from a list. It returns the original sequence
-- if the sequence doesn't start with the given prefix.
--
-- -- dropPrefix "Mr. " "Mr. Men" == "Men" -- dropPrefix "Mr. " "Dr. Men" == "Dr. Men" --dropPrefix :: Eq a => [a] -> [a] -> [a] -- | Drops the given suffix from a list. It returns the original sequence -- if the sequence doesn't end with the given suffix. -- --
-- dropSuffix "!" "Hello World!" == "Hello World" -- dropSuffix "!" "Hello World!!" == "Hello World!" -- dropSuffix "!" "Hello World." == "Hello World." --dropSuffix :: Eq a => [a] -> [a] -> [a] -- | A variant of words with a custom test. In particular, adjacent -- separators are discarded, as are leading or trailing separators. -- --
-- wordsBy (== ':') "::xyz:abc::123::" == ["xyz","abc","123"] -- \s -> wordsBy isSpace s == words s --wordsBy :: (a -> Bool) -> [a] -> [[a]] -- | A variant of lines with a custom test. In particular, if there -- is a trailing separator it will be discarded. -- --
-- linesBy (== ':') "::xyz:abc::123::" == ["","","xyz","abc","","123",""] -- \s -> linesBy (== '\n') s == lines s -- linesBy (== ';') "my;list;here;" == ["my","list","here"] --linesBy :: (a -> Bool) -> [a] -> [[a]] -- | Find the first instance of needle in haystack. The -- first element of the returned tuple is the prefix of haystack -- before needle is matched. The second is the remainder of -- haystack, starting with the match. If you want the remainder -- without the match, use stripInfix. -- --
-- breakOn "::" "a::b::c" == ("a", "::b::c")
-- breakOn "/" "foobar" == ("foobar", "")
-- \needle haystack -> let (prefix,match) = breakOn needle haystack in prefix ++ match == haystack
--
breakOn :: Eq a => [a] -> [a] -> ([a], [a])
-- | Similar to breakOn, but searches from the end of the string.
--
-- The first element of the returned tuple is the prefix of
-- haystack up to and including the last match of
-- needle. The second is the remainder of haystack,
-- following the match.
--
--
-- breakOnEnd "::" "a::b::c" == ("a::b::", "c")
--
breakOnEnd :: Eq a => [a] -> [a] -> ([a], [a])
-- | Break a list into pieces separated by the first list argument,
-- consuming the delimiter. An empty delimiter is invalid, and will cause
-- an error to be raised.
--
-- -- splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"] -- splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""] -- splitOn "x" "x" == ["",""] -- splitOn "x" "" == [""] -- \s x -> s /= "" ==> intercalate s (splitOn s x) == x -- \c x -> splitOn [c] x == split (==c) x --splitOn :: (Partial, Eq a) => [a] -> [a] -> [[a]] -- | Splits a list into components delimited by separators, where the -- predicate returns True for a separator element. The resulting -- components do not contain the separators. Two adjacent separators -- result in an empty component in the output. -- --
-- split (== 'a') "aabbaca" == ["","","bb","c",""] -- split (== 'a') "" == [""] -- split (== ':') "::xyz:abc::123::" == ["","","xyz","abc","","123","",""] -- split (== ',') "my,list,here" == ["my","list","here"] --split :: (a -> Bool) -> [a] -> [[a]] -- | Split a list into chunks of a given size. The last chunk may contain -- fewer than n elements. The chunk size must be positive. -- --
-- chunksOf 3 "my test" == ["my ","tes","t"] -- chunksOf 3 "mytest" == ["myt","est"] -- chunksOf 8 "" == [] -- chunksOf 0 "test" == undefined --chunksOf :: Partial => Int -> [a] -> [[a]] -- | A total head with a default value. -- --
-- headDef 1 [] == 1 -- headDef 1 [2,3,4] == 2 -- \x xs -> headDef x xs == fromMaybe x (listToMaybe xs) --headDef :: a -> [a] -> a -- | A total last with a default value. -- --
-- lastDef 1 [] == 1 -- lastDef 1 [2,3,4] == 4 -- \x xs -> lastDef x xs == last (x:xs) --lastDef :: a -> [a] -> a -- | A composition of not and null. -- --
-- notNull [] == False -- notNull [1] == True -- \xs -> notNull xs == not (null xs) --notNull :: [a] -> Bool -- | Non-recursive transform over a list, like maybe. -- --
-- list 1 (\v _ -> v - 2) [5,6,7] == 3 -- list 1 (\v _ -> v - 2) [] == 1 -- \nil cons xs -> maybe nil (uncurry cons) (uncons xs) == list nil cons xs --list :: b -> (a -> [a] -> b) -> [a] -> b -- | If the list is empty returns Nothing, otherwise returns the -- init and the last. -- --
-- unsnoc "test" == Just ("tes",'t')
-- unsnoc "" == Nothing
-- \xs -> unsnoc xs == if null xs then Nothing else Just (init xs, last xs)
--
unsnoc :: [a] -> Maybe ([a], a)
-- | Append an element to the start of a list, an alias for '(:)'.
--
-- -- cons 't' "est" == "test" -- \x xs -> uncons (cons x xs) == Just (x,xs) --cons :: a -> [a] -> [a] -- | Append an element to the end of a list, takes O(n) time. -- --
-- snoc "tes" 't' == "test" -- \xs x -> unsnoc (snoc xs x) == Just (xs,x) --snoc :: [a] -> a -> [a] -- | Equivalent to drop 1, but likely to be faster and a single -- lexeme. -- --
-- drop1 "" == "" -- drop1 "test" == "est" -- \xs -> drop 1 xs == drop1 xs --drop1 :: [a] -> [a] -- | Equivalent to dropEnd 1, but likely to be faster and a single -- lexeme. -- --
-- dropEnd1 "" == "" -- dropEnd1 "test" == "tes" -- \xs -> dropEnd 1 xs == dropEnd1 xs --dropEnd1 :: [a] -> [a] -- | Version on concatMap generalised to a Monoid rather than -- just a list. -- --
-- mconcatMap Sum [1,2,3] == Sum 6 -- \f xs -> mconcatMap f xs == concatMap f xs --mconcatMap :: Monoid b => (a -> b) -> [a] -> b -- | Enumerate all the values of an Enum, from minBound to -- maxBound. -- --
-- enumerate == [False, True] --enumerate :: (Enum a, Bounded a) => [a] -- | A combination of group and sort. -- --
-- groupSort [(1,'t'),(3,'t'),(2,'e'),(2,'s')] == [(1,"t"),(2,"es"),(3,"t")] -- \xs -> map fst (groupSort xs) == sort (nub (map fst xs)) -- \xs -> concatMap snd (groupSort xs) == map snd (sortOn fst xs) --groupSort :: Ord k => [(k, v)] -> [(k, [v])] -- | A combination of group and sort, using a part of the -- value to compare on. -- --
-- groupSortOn length ["test","of","sized","item"] == [["of"],["test","item"],["sized"]] --groupSortOn :: Ord b => (a -> b) -> [a] -> [[a]] -- | A combination of group and sort, using a predicate to -- compare on. -- --
-- groupSortBy (compare `on` length) ["test","of","sized","item"] == [["of"],["test","item"],["sized"]] --groupSortBy :: (a -> a -> Ordering) -> [a] -> [[a]] -- | O(n log n). The nubOrd function removes duplicate -- elements from a list. In particular, it keeps only the first -- occurrence of each element. Unlike the standard nub operator, -- this version requires an Ord instance and consequently runs -- asymptotically faster. -- --
-- nubOrd "this is a test" == "this ae"
-- nubOrd (take 4 ("this" ++ undefined)) == "this"
-- \xs -> nubOrd xs == nub xs
--
nubOrd :: Ord a => [a] -> [a]
-- | A version of nubOrd with a custom predicate.
--
-- -- nubOrdBy (compare `on` length) ["a","test","of","this"] == ["a","test","of"] --nubOrdBy :: (a -> a -> Ordering) -> [a] -> [a] -- | A version of nubOrd which operates on a portion of the value. -- --
-- nubOrdOn length ["a","test","of","this"] == ["a","test","of"] --nubOrdOn :: Ord b => (a -> b) -> [a] -> [a] -- | DEPRECATED Use nubOrdOn, since this function is -- _O(n^2)_. -- -- A version of nub where the equality is done on some extracted -- value. nubOn f is equivalent to nubBy ((==) on -- f), but has the performance advantage of only evaluating -- f once for each element in the input list. -- | Deprecated: Use nubOrdOn, since this function is O(n^2) nubOn :: Eq b => (a -> b) -> [a] -> [a] -- | A version of group where the equality is done on some extracted -- value. groupOn :: Eq b => (a -> b) -> [a] -> [[a]] -- | O(n log n). The nubSort function sorts and removes -- duplicate elements from a list. In particular, it keeps only the first -- occurrence of each element. -- --
-- nubSort "this is a test" == " aehist" -- \xs -> nubSort xs == nub (sort xs) --nubSort :: Ord a => [a] -> [a] -- | A version of nubSort with a custom predicate. -- --
-- nubSortBy (compare `on` length) ["a","test","of","this"] == ["a","of","test"] --nubSortBy :: (a -> a -> Ordering) -> [a] -> [a] -- | A version of nubSort which operates on a portion of the value. -- --
-- nubSortOn length ["a","test","of","this"] == ["a","of","test"] --nubSortOn :: Ord b => (a -> b) -> [a] -> [a] -- | A version of maximum where the comparison is done on some -- extracted value. Raises an error if the list is empty. Only calls the -- function once per element. -- --
-- maximumOn id [] == undefined -- maximumOn length ["test","extra","a"] == "extra" --maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a -- | A version of minimum where the comparison is done on some -- extracted value. Raises an error if the list is empty. Only calls the -- function once per element. -- --
-- minimumOn id [] == undefined -- minimumOn length ["test","extra","a"] == "a" --minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a -- | Are two lists disjoint, with no elements in common. -- --
-- disjoint [1,2,3] [4,5] == True -- disjoint [1,2,3] [4,1] == False --disjoint :: Eq a => [a] -> [a] -> Bool -- | Are all elements the same. -- --
-- allSame [1,1,2] == False -- allSame [1,1,1] == True -- allSame [1] == True -- allSame [] == True -- allSame (1:1:2:undefined) == False -- \xs -> allSame xs == (length (nub xs) <= 1) --allSame :: Eq a => [a] -> Bool -- | Is there any element which occurs more than once. -- --
-- anySame [1,1,2] == True -- anySame [1,2,3] == False -- anySame (1:2:1:undefined) == True -- anySame [] == False -- \xs -> anySame xs == (length (nub xs) < length xs) --anySame :: Eq a => [a] -> Bool -- | Apply some operation repeatedly, producing an element of output and -- the remainder of the list. -- --
-- \xs -> repeatedly (splitAt 3) xs == chunksOf 3 xs -- \xs -> repeatedly word1 (trim xs) == words xs -- \xs -> repeatedly line1 xs == lines xs --repeatedly :: ([a] -> (b, [a])) -> [a] -> [b] -- | Find the first element of a list for which the operation returns -- Just, along with the result of the operation. Like find -- but useful where the function also computes some expensive information -- that can be reused. Particular useful when the function is monadic, -- see firstJustM. -- --
-- firstJust id [Nothing,Just 3] == Just 3 -- firstJust id [Nothing,Nothing] == Nothing --firstJust :: (a -> Maybe b) -> [a] -> Maybe b -- | A merging of unzip and concat. -- --
-- concatUnzip [("a","AB"),("bc","C")] == ("abc","ABC")
--
concatUnzip :: [([a], [b])] -> ([a], [b])
-- | A merging of unzip3 and concat.
--
--
-- concatUnzip3 [("a","AB",""),("bc","C","123")] == ("abc","ABC","123")
--
concatUnzip3 :: [([a], [b], [c])] -> ([a], [b], [c])
-- | zip against an enumeration. Never truncates the output - raises
-- an error if the enumeration runs out.
--
-- -- \i xs -> zip [i..] xs == zipFrom i xs -- zipFrom False [1..3] == [(False,1),(True, 2)] --zipFrom :: Enum a => a -> [b] -> [(a, b)] -- | zipFrom generalised to any combining operation. Never truncates -- the output - raises an error if the enumeration runs out. -- --
-- \i xs -> zipWithFrom (,) i xs == zipFrom i xs --zipWithFrom :: Enum a => (a -> b -> c) -> a -> [b] -> [c] -- | Replace a subsequence everywhere it occurs. The first argument must -- not be the empty list. -- --
-- replace "el" "_" "Hello Bella" == "H_lo B_la" -- replace "el" "e" "Hello" == "Helo" -- replace "" "e" "Hello" == undefined -- \xs ys -> not (null xs) ==> replace xs xs ys == ys --replace :: (Partial, Eq a) => [a] -> [a] -> [a] -> [a] -- | Merge two lists which are assumed to be ordered. -- --
-- merge "ace" "bd" == "abcde" -- \xs ys -> merge (sort xs) (sort ys) == sort (xs ++ ys) --merge :: Ord a => [a] -> [a] -> [a] -- | Like merge, but with a custom ordering function. mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a] instance GHC.Show.Show a => GHC.Show.Show (Data.List.Extra.RB a) instance GHC.Show.Show Data.List.Extra.Color -- | This module extends Data.Version with extra utilities. The -- package also exports the existing Data.Version functions. module Data.Version.Extra -- | Read a Version or throw an exception. -- --
-- \x -> readVersion (showVersion x) == x -- readVersion "hello" == undefined --readVersion :: Partial => String -> Version -- | Extra functions for working with NonEmpty lists. The package -- also exports the existing Data.List.NonEmpty functions. module Data.List.NonEmpty.Extra -- | O(n). Append an element to a list. -- --
-- [1,2,3] |: 4 |> 5 == 1 :| [2,3,4,5] --(|:) :: [a] -> a -> NonEmpty a infixl 5 |: -- | O(n). Append an element to a non-empty list. -- --
-- (1 :| [2,3]) |> 4 |> 5 == 1 :| [2,3,4,5] --(|>) :: NonEmpty a -> a -> NonEmpty a infixl 5 |> -- | Synonym for |>. snoc :: NonEmpty a -> a -> NonEmpty a -- | Append a list to a non-empty list. -- --
-- appendl (1 :| [2,3]) [4,5] == 1 :| [2,3,4,5] --appendl :: NonEmpty a -> [a] -> NonEmpty a -- | Append a non-empty list to a list. -- --
-- appendr [1,2,3] (4 :| [5]) == 1 :| [2,3,4,5] --appendr :: [a] -> NonEmpty a -> NonEmpty a -- | Sort by comparing the results of a function applied to each element. -- The sort is stable, and the function is evaluated only once for each -- element. sortOn :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a -- | Return the union of two non-empty lists. Duplicates, and elements of -- the first list, are removed from the the second list, but if the first -- list contains duplicates, so will the result. -- --
-- (1 :| [3, 5, 3]) `union` (4 :| [5, 3, 5, 2]) == 1 :| [3, 5, 3, 4, 2] --union :: Eq a => NonEmpty a -> NonEmpty a -> NonEmpty a -- | The non-overloaded version of union. unionBy :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a -> NonEmpty a -- | nubOrd for NonEmpty. Behaves the same as -- nubOrd. -- --
-- Data.List.NonEmpty.Extra.nubOrd (1 :| [2, 3, 3, 4, 1, 2]) == 1 :| [2, 3, 4] -- \xs -> Data.List.NonEmpty.Extra.nubOrd xs == Data.List.NonEmpty.Extra.nub xs --nubOrd :: Ord a => NonEmpty a -> NonEmpty a -- | nubOrdBy for NonEmpty. Behaves the same as -- nubOrdBy. -- --
-- Data.List.NonEmpty.Extra.nubOrdBy (compare `on` Data.List.length) ("a" :| ["test","of","this"]) == "a" :| ["test","of"]
--
nubOrdBy :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
-- | nubOrdOn for NonEmpty. Behaves the same as
-- nubOrdOn.
--
--
-- Data.List.NonEmpty.Extra.nubOrdOn Data.List.length ("a" :| ["test","of","this"]) == "a" :| ["test","of"]
--
nubOrdOn :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a
-- | The largest element of a non-empty list.
maximum1 :: Ord a => NonEmpty a -> a
-- | The least element of a non-empty list.
minimum1 :: Ord a => NonEmpty a -> a
-- | The largest element of a non-empty list with respect to the given
-- comparison function.
maximumBy1 :: (a -> a -> Ordering) -> NonEmpty a -> a
-- | The least element of a non-empty list with respect to the given
-- comparison function.
minimumBy1 :: (a -> a -> Ordering) -> NonEmpty a -> a
-- | A version of maximum1 where the comparison is done on some
-- extracted value.
maximumOn1 :: Ord b => (a -> b) -> NonEmpty a -> a
-- | A version of minimum1 where the comparison is done on some
-- extracted value.
minimumOn1 :: Ord b => (a -> b) -> NonEmpty a -> a
-- | This module extends Data.Either with extra operations,
-- particularly to quickly extract from inside an Either. Some of
-- these operations are partial, and should be used with care in
-- production-quality code.
--
-- If you need more Either functions see the either.
module Data.Either.Extra
-- | Return the contents of a Left-value or a default value
-- otherwise.
--
-- -- >>> fromLeft 1 (Left 3) -- 3 -- -- >>> fromLeft 1 (Right "foo") -- 1 --fromLeft :: () => a -> Either a b -> a -- | Return the contents of a Right-value or a default value -- otherwise. -- --
-- >>> fromRight 1 (Right 3) -- 3 -- -- >>> fromRight 1 (Left "foo") -- 1 --fromRight :: () => b -> Either a b -> b -- | Pull the value out of an Either where both alternatives have -- the same type. -- --
-- \x -> fromEither (Left x ) == x -- \x -> fromEither (Right x) == x --fromEither :: Either a a -> a -- | The fromLeft' function extracts the element out of a -- Left and throws an error if its argument is Right. Much -- like fromJust, using this function in polished code is -- usually a bad idea. -- --
-- \x -> fromLeft' (Left x) == x -- \x -> fromLeft' (Right x) == undefined --fromLeft' :: Partial => Either l r -> l -- | The fromRight' function extracts the element out of a -- Right and throws an error if its argument is Left. Much -- like fromJust, using this function in polished code is -- usually a bad idea. -- --
-- \x -> fromRight' (Right x) == x -- \x -> fromRight' (Left x) == undefined --fromRight' :: Partial => Either l r -> r -- | Given an Either, convert it to a Maybe, where -- Left becomes Nothing. -- --
-- \x -> eitherToMaybe (Left x) == Nothing -- \x -> eitherToMaybe (Right x) == Just x --eitherToMaybe :: Either a b -> Maybe b -- | Given a Maybe, convert it to an Either, providing a -- suitable value for the Left should the value be Nothing. -- --
-- \a b -> maybeToEither a (Just b) == Right b -- \a -> maybeToEither a Nothing == Left a --maybeToEither :: a -> Maybe b -> Either a b -- | The mapLeft function takes a function and applies it to an -- Either value iff the value takes the form Left _. -- --
-- mapLeft show (Left 1) == Left "1" -- mapLeft show (Right True) == Right True --mapLeft :: (a -> c) -> Either a b -> Either c b -- | The mapRight function takes a function and applies it to an -- Either value iff the value takes the form Right _. -- --
-- mapRight show (Left 1) == Left 1 -- mapRight show (Right True) == Right "True" --mapRight :: (b -> c) -> Either a b -> Either a c -- | Extra functions for Control.Exception. These functions provide -- retrying, showing in the presence of exceptions, and functions to -- catch/ignore exceptions, including monomorphic (no Exception -- context) versions. -- -- If you want to use a safer set of exceptions see the -- safe-exceptions package. module Control.Exception.Extra -- | A constraint which documents that a function is partial, and on GHC -- 8.0 and above produces a stack trace on failure. For example: -- --
-- myHead :: Partial => [a] -> a -- myHead [] = error "bad" -- myHead (x:xs) = x ---- -- When using Partial with GHC 7.8 or below you need to enable the -- language feature ConstraintKinds, e.g. {-# LANGUAGE -- ConstraintKinds #-} at the top of the file. type Partial = HasCallStack -- | Retry an operation at most n times (n must be positive). -- If the operation fails the nth time it will throw that final -- exception. -- --
-- retry 1 (print "x") == print "x" -- retry 3 (fail "die") == fail "die" --retry :: Int -> IO a -> IO a -- | Retry an operation at most n times (n must be positive), -- while the exception value and type match a predicate. If the operation -- fails the nth time it will throw that final exception. retryBool :: Exception e => (e -> Bool) -> Int -> IO a -> IO a -- | A variant of error that does not produce a stack trace. errorWithoutStackTrace :: () => [Char] -> a -- | Show a value, but if the result contains exceptions, produce -- <Exception>. Defined as stringException . -- show. Particularly useful for printing exceptions to users, -- remembering that exceptions can themselves contain undefined values. showException :: Show e => e -> IO String -- | Fully evaluate an input String. If the String contains embedded -- exceptions it will produce <Exception>. -- --
-- stringException "test" == pure "test"
-- stringException ("test" ++ undefined) == pure "test<Exception>"
-- stringException ("test" ++ undefined ++ "hello") == pure "test<Exception>"
-- stringException ['t','e','s','t',undefined] == pure "test<Exception>"
--
stringException :: String -> IO String
-- | An IO action that when evaluated calls error, in the
-- IO monad. Note that while fail in IO raises an
-- IOException, this function raises an ErrorCall exception
-- with a call stack.
--
-- -- catch (errorIO "Hello") (\(ErrorCall x) -> pure x) == pure "Hello" -- seq (errorIO "foo") (print 1) == print 1 --errorIO :: Partial => String -> IO a -- | Ignore any exceptions thrown by the action. -- --
-- ignore (print 1) == print 1 -- ignore (fail "die") == pure () --ignore :: IO () -> IO () -- | A version of catch without the Exception context, -- restricted to SomeException, so catches all exceptions. catch_ :: IO a -> (SomeException -> IO a) -> IO a -- | Like catch_ but for handle handle_ :: (SomeException -> IO a) -> IO a -> IO a -- | Like catch_ but for try try_ :: IO a -> IO (Either SomeException a) -- | Like catch_ but for catchJust catchJust_ :: (SomeException -> Maybe b) -> IO a -> (b -> IO a) -> IO a -- | Like catch_ but for handleJust handleJust_ :: (SomeException -> Maybe b) -> (b -> IO a) -> IO a -> IO a -- | Like catch_ but for tryJust tryJust_ :: (SomeException -> Maybe b) -> IO a -> IO (Either b a) -- | Catch an exception if the predicate passes, then call the handler with -- the original exception. As an example: -- --
-- readFileExists x == catchBool isDoesNotExistError (readFile "myfile") (const $ pure "") --catchBool :: Exception e => (e -> Bool) -> IO a -> (e -> IO a) -> IO a -- | Like catchBool but for handle. handleBool :: Exception e => (e -> Bool) -> (e -> IO a) -> IO a -> IO a -- | Like catchBool but for try. tryBool :: Exception e => (e -> Bool) -> IO a -> IO (Either e a) -- | Extra functions for Control.Monad. These functions provide -- looping, list operations and booleans. If you need a wider selection -- of monad loops and list generalisations, see monad-loops. module Control.Monad.Extra -- | Perform some operation on Just, given the field inside the -- Just. -- --
-- whenJust Nothing print == pure () -- whenJust (Just 1) print == print 1 --whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m () -- | Like whenJust, but where the test can be monadic. whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m () -- | Like when, but return either Nothing if the predicate -- was False, of Just with the result of the computation. -- --
-- whenMaybe True (print 1) == fmap Just (print 1) -- whenMaybe False (print 1) == pure Nothing --whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a) -- | Like whenMaybe, but where the test can be monadic. whenMaybeM :: Monad m => m Bool -> m a -> m (Maybe a) -- | The identity function which requires the inner argument to be -- (). Useful for functions with overloaded return types. -- --
-- \(x :: Maybe ()) -> unit x == x --unit :: m () -> m () -- | Monadic generalisation of maybe. maybeM :: Monad m => m b -> (a -> m b) -> m (Maybe a) -> m b -- | Monadic generalisation of fromMaybe. fromMaybeM :: Monad m => m a -> m (Maybe a) -> m a -- | Monadic generalisation of either. eitherM :: Monad m => (a -> m c) -> (b -> m c) -> m (Either a b) -> m c -- | A looping operation, where the predicate returns Left as a seed -- for the next loop or Right to abort the loop. -- --
-- loop (\x -> if x < 10 then Left $ x * 2 else Right $ show x) 1 == "16" --loop :: (a -> Either a b) -> a -> b -- | A monadic version of loop, where the predicate returns -- Left as a seed for the next loop or Right to abort the -- loop. loopM :: Monad m => (a -> m (Either a b)) -> a -> m b -- | Keep running an operation until it becomes False. As an -- example: -- --
-- whileM $ do sleep 0.1; notM $ doesFileExist "foo.txt" -- readFile "foo.txt" ---- -- If you need some state persisted between each test, use loopM. whileM :: Monad m => m Bool -> m () -- | A version of partition that works with a monadic predicate. -- --
-- partitionM (Just . even) [1,2,3] == Just ([2], [1,3]) -- partitionM (const Nothing) [1,2,3] == Nothing --partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a]) -- | A version of concatMap that works with a monadic predicate. concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b] -- | Like concatMapM, but has its arguments flipped, so can be used -- instead of the common fmap concat $ forM pattern. concatForM :: Monad m => [a] -> (a -> m [b]) -> m [b] -- | A version of mconcatMap that works with a monadic predicate. mconcatMapM :: (Monad m, Monoid b) => (a -> m b) -> [a] -> m b -- | A version of mapMaybe that works with a monadic predicate. mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b] -- | Like find, but where the test can be monadic. -- --
-- findM (Just . isUpper) "teST" == Just (Just 'S') -- findM (Just . isUpper) "test" == Just Nothing -- findM (Just . const True) ["x",undefined] == Just (Just "x") --findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) -- | Like findM, but also allows you to compute some additional -- information in the predicate. firstJustM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b) -- | A variant of foldM that has no base case, and thus may only be -- applied to non-empty lists. -- --
-- fold1M (\x y -> Just x) [] == undefined -- fold1M (\x y -> Just $ x + y) [1, 2, 3] == Just 6 --fold1M :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m a -- | Like fold1M but discards the result. fold1M_ :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m () -- | Like when, but where the test can be monadic. whenM :: Monad m => m Bool -> m () -> m () -- | Like unless, but where the test can be monadic. unlessM :: Monad m => m Bool -> m () -> m () -- | Like if, but where the test can be monadic. ifM :: Monad m => m Bool -> m a -> m a -> m a -- | Like not, but where the test can be monadic. notM :: Functor m => m Bool -> m Bool -- | The lazy || operator lifted to a monad. If the first argument -- evaluates to True the second argument will not be evaluated. -- --
-- Just True ||^ undefined == Just True -- Just False ||^ Just True == Just True -- Just False ||^ Just False == Just False --(||^) :: Monad m => m Bool -> m Bool -> m Bool -- | The lazy && operator lifted to a monad. If the first -- argument evaluates to False the second argument will not be -- evaluated. -- --
-- Just False &&^ undefined == Just False -- Just True &&^ Just True == Just True -- Just True &&^ Just False == Just False --(&&^) :: Monad m => m Bool -> m Bool -> m Bool -- | A version of or lifted to a monad. Retains the short-circuiting -- behaviour. -- --
-- orM [Just False,Just True ,undefined] == Just True -- orM [Just False,Just False,undefined] == undefined -- \xs -> Just (or xs) == orM (map Just xs) --orM :: Monad m => [m Bool] -> m Bool -- | A version of and lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- andM [Just True,Just False,undefined] == Just False -- andM [Just True,Just True ,undefined] == undefined -- \xs -> Just (and xs) == andM (map Just xs) --andM :: Monad m => [m Bool] -> m Bool -- | A version of any lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- anyM Just [False,True ,undefined] == Just True -- anyM Just [False,False,undefined] == undefined -- \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs) --anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool -- | A version of all lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- allM Just [True,False,undefined] == Just False -- allM Just [True,True ,undefined] == undefined -- \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs) --allM :: Monad m => (a -> m Bool) -> [a] -> m Bool -- | Extra functions for Control.Concurrent. -- -- This module includes three new types of MVar, namely -- Lock (no associated value), Var (never empty) and -- Barrier (filled at most once). See this blog post for -- examples and justification. -- -- If you need greater control of exceptions and threads see the -- slave-thread package. If you need elaborate relationships -- between threads see the async package. module Control.Concurrent.Extra -- | On GHC 7.6 and above with the -threaded flag, brackets a call -- to setNumCapabilities. On lower versions (which lack -- setNumCapabilities) this function just runs the argument -- action. withNumCapabilities :: Int -> IO a -> IO a -- | Given an action, produce a wrapped action that runs at most once. If -- the function raises an exception, the same exception will be reraised -- each time. -- --
-- let x ||| y = do t1 <- onceFork x; t2 <- onceFork y; t1; t2 -- \(x :: IO Int) -> void (once x) == pure () -- \(x :: IO Int) -> join (once x) == x -- \(x :: IO Int) -> (do y <- once x; y; y) == x -- \(x :: IO Int) -> (do y <- once x; y ||| y) == x --once :: IO a -> IO (IO a) -- | Like once, but immediately starts running the computation on a -- background thread. -- --
-- \(x :: IO Int) -> join (onceFork x) == x -- \(x :: IO Int) -> (do a <- onceFork x; a; a) == x --onceFork :: IO a -> IO (IO a) -- | Like an MVar, but has no value. Used to guarantee -- single-threaded access, typically to some system resource. As an -- example: -- --
-- lock <- newLock -- let output = withLock . putStrLn -- forkIO $ do ...; output "hello" -- forkIO $ do ...; output "world" ---- -- Here we are creating a lock to ensure that when writing output our -- messages do not get interleaved. This use of MVar never blocks -- on a put. It is permissible, but rare, that a withLock contains a -- withLock inside it - but if so, watch out for deadlocks. data Lock -- | Create a new Lock. newLock :: IO Lock -- | Perform some operation while holding Lock. Will prevent all -- other operations from using the Lock while the action is -- ongoing. withLock :: Lock -> IO a -> IO a -- | Like withLock but will never block. If the operation cannot be -- executed immediately it will return Nothing. withLockTry :: Lock -> IO a -> IO (Maybe a) -- | Like an MVar, but must always be full. Used to operate on a -- mutable variable in a thread-safe way. As an example: -- --
-- hits <- newVar 0
-- forkIO $ do ...; modifyVar_ hits (+1); ...
-- i <- readVar hits
-- print ("HITS",i)
--
--
-- Here we have a variable which we modify atomically, so modifications
-- are not interleaved. This use of MVar never blocks on a put. No
-- modifyVar operation should ever block, and they should always complete
-- in a reasonable timeframe. A Var should not be used to protect
-- some external resource, only the variable contained within.
-- Information from a readVar should not be subsequently inserted
-- back into the Var.
data Var a
-- | Create a new Var with a value.
newVar :: a -> IO (Var a)
-- | Read the current value of the Var.
readVar :: Var a -> IO a
-- | Write a value to become the new value of Var.
writeVar :: Var a -> a -> IO ()
-- | Modify a Var producing a new value and a return result.
modifyVar :: Var a -> (a -> IO (a, b)) -> IO b
-- | Modify a Var, a restricted version of modifyVar.
modifyVar_ :: Var a -> (a -> IO a) -> IO ()
-- | Perform some operation using the value in the Var, a restricted
-- version of modifyVar.
withVar :: Var a -> (a -> IO b) -> IO b
-- | Starts out empty, then is filled exactly once. As an example:
--
-- -- bar <- newBarrier -- forkIO $ do ...; val <- ...; signalBarrier bar val -- print =<< waitBarrier bar ---- -- Here we create a barrier which will contain some computed value. A -- thread is forked to fill the barrier, while the main thread waits for -- it to complete. A barrier has similarities to a future or promise from -- other languages, has been known as an IVar in other Haskell work, and -- in some ways is like a manually managed thunk. data Barrier a -- | Create a new Barrier. newBarrier :: IO (Barrier a) -- | Write a value into the Barrier, releasing anyone at -- waitBarrier. Any subsequent attempts to signal the -- Barrier will throw an exception. signalBarrier :: Partial => Barrier a -> a -> IO () -- | Wait until a barrier has been signaled with signalBarrier. waitBarrier :: Barrier a -> IO a -- | A version of waitBarrier that never blocks, returning -- Nothing if the barrier has not yet been signaled. waitBarrierMaybe :: Barrier a -> IO (Maybe a) -- | Extra directory functions. Most of these functions provide cleaned up -- and generalised versions of getDirectoryContents, see -- listContents for the differences. module System.Directory.Extra -- | Create a directory with permissions so that only the current user can -- view it. On Windows this function is equivalent to -- createDirectory. createDirectoryPrivate :: String -> IO () -- | List the files and directories directly within a directory. Each -- result will be prefixed by the query directory, and the special -- directories . and .. will be ignored. Intended as a -- cleaned up version of getDirectoryContents. -- --
-- withTempDir $ \dir -> do writeFile (dir </> "test.txt") ""; (== [dir </> "test.txt"]) <$> listContents dir -- let touch = mapM_ $ \x -> createDirectoryIfMissing True (takeDirectory x) >> writeFile x "" -- let listTest op as bs = withTempDir $ \dir -> do touch $ map (dir </>) as; res <- op dir; pure $ map (drop (length dir + 1)) res == bs -- listTest listContents ["bar.txt","foo/baz.txt","zoo"] ["bar.txt","foo","zoo"] --listContents :: FilePath -> IO [FilePath] -- | Like listContents, but only returns the directories in a -- directory, not the files. Each directory will be prefixed by the query -- directory. -- --
-- listTest listDirectories ["bar.txt","foo/baz.txt","zoo"] ["foo"] --listDirectories :: FilePath -> IO [FilePath] -- | Like listContents, but only returns the files in a directory, -- not other directories. Each file will be prefixed by the query -- directory. -- --
-- listTest listFiles ["bar.txt","foo/baz.txt","zoo"] ["bar.txt","zoo"] --listFiles :: FilePath -> IO [FilePath] -- | Like listFilesRecursive, but with a predicate to decide where -- to recurse into. Typically directories starting with . would -- be ignored. The initial argument directory will have the test applied -- to it. -- --
-- listTest (listFilesInside $ pure . not . isPrefixOf "." . takeFileName) -- ["bar.txt","foo" </> "baz.txt",".foo" </> "baz2.txt", "zoo"] ["bar.txt","zoo","foo" </> "baz.txt"] -- listTest (listFilesInside $ const $ pure False) ["bar.txt"] [] --listFilesInside :: (FilePath -> IO Bool) -> FilePath -> IO [FilePath] -- | Like listFiles, but goes recursively through all -- subdirectories. This function will follow symlinks, and if they form a -- loop, this function will not terminate. -- --
-- listTest listFilesRecursive ["bar.txt","zoo","foo" </> "baz.txt"] ["bar.txt","zoo","foo" </> "baz.txt"] --listFilesRecursive :: FilePath -> IO [FilePath] -- | Extra functions for System.Environment. All these functions are -- available in later GHC versions, but this code works all the way back -- to GHC 7.2. -- -- Currently this module has no functionality beyond -- System.Environment. module System.Environment.Extra -- | More IO functions. The functions include ones for reading files with -- specific encodings, strictly reading files, and writing files with -- encodings. There are also some simple temporary file functions, more -- advanced alternatives can be found in the exceptions package. module System.IO.Extra -- | Capture the stdout and stderr of a computation. -- --
-- captureOutput (print 1) == pure ("1\n",())
--
captureOutput :: IO a -> IO (String, a)
-- | Execute an action with a custom BufferMode, a wrapper around
-- hSetBuffering.
withBuffering :: Handle -> BufferMode -> IO a -> IO a
-- | Like readFile, but setting an encoding.
readFileEncoding :: TextEncoding -> FilePath -> IO String
-- | Like readFile, but with the encoding utf8.
readFileUTF8 :: FilePath -> IO String
-- | Like readFile, but for binary files.
readFileBinary :: FilePath -> IO String
-- | A strict version of readFile. When the string is produced, the
-- entire file will have been read into memory and the file handle will
-- have been closed. Closing the file handle does not rely on the garbage
-- collector.
--
-- -- \(filter isHexDigit -> s) -> fmap (== s) $ withTempFile $ \file -> do writeFile file s; readFile' file --readFile' :: FilePath -> IO String -- | A strict version of readFileEncoding, see readFile' for -- details. readFileEncoding' :: TextEncoding -> FilePath -> IO String -- | A strict version of readFileUTF8, see readFile' for -- details. readFileUTF8' :: FilePath -> IO String -- | A strict version of readFileBinary, see readFile' for -- details. readFileBinary' :: FilePath -> IO String -- | Write a file with a particular encoding. writeFileEncoding :: TextEncoding -> FilePath -> String -> IO () -- | Write a file with the utf8 encoding. -- --
-- \s -> withTempFile $ \file -> do writeFileUTF8 file s; fmap (== s) $ readFileUTF8' file --writeFileUTF8 :: FilePath -> String -> IO () -- | Write a binary file. -- --
-- \(ASCIIString s) -> withTempFile $ \file -> do writeFileBinary file s; fmap (== s) $ readFileBinary' file --writeFileBinary :: FilePath -> String -> IO () -- | Create a temporary file in the temporary directory. The file will be -- deleted after the action completes (provided the file is not still -- open). The FilePath will not have any file extension, will -- exist, and will be zero bytes long. If you require a file with a -- specific name, use withTempDir. -- --
-- withTempFile doesFileExist == pure True -- (doesFileExist =<< withTempFile pure) == pure False -- withTempFile readFile' == pure "" --withTempFile :: (FilePath -> IO a) -> IO a -- | Create a temporary directory inside the system temporary directory. -- The directory will be deleted after the action completes. -- --
-- withTempDir doesDirectoryExist == pure True -- (doesDirectoryExist =<< withTempDir pure) == pure False -- withTempDir listFiles == pure [] --withTempDir :: (FilePath -> IO a) -> IO a -- | Provide a function to create a temporary file, and a way to delete a -- temporary file. Most users should use withTempFile which -- combines these operations. newTempFile :: IO (FilePath, IO ()) -- | Provide a function to create a temporary directory, and a way to -- delete a temporary directory. Most users should use withTempDir -- which combines these operations. newTempDir :: IO (FilePath, IO ()) -- | Like newTempFile but using a custom temporary directory. newTempFileWithin :: FilePath -> IO (FilePath, IO ()) -- | Like newTempDir but using a custom temporary directory. newTempDirWithin :: FilePath -> IO (FilePath, IO ()) -- | Returns True if both files have the same content. Raises an -- error if either file is missing. -- --
-- fileEq "does_not_exist1" "does_not_exist2" == undefined -- fileEq "does_not_exist" "does_not_exist" == undefined -- withTempFile $ \f1 -> fileEq "does_not_exist" f1 == undefined -- withTempFile $ \f1 -> withTempFile $ \f2 -> fileEq f1 f2 -- withTempFile $ \f1 -> withTempFile $ \f2 -> writeFile f1 "a" >> writeFile f2 "a" >> fileEq f1 f2 -- withTempFile $ \f1 -> withTempFile $ \f2 -> writeFile f1 "a" >> writeFile f2 "b" >> notM (fileEq f1 f2) --fileEq :: FilePath -> FilePath -> IO Bool -- | Extra functions for the current system info. module System.Info.Extra -- | Return True on Windows and False otherwise. A runtime -- version of #ifdef minw32_HOST_OS. Equivalent to os == -- "mingw32", but: more efficient; doesn't require typing an easily -- mistypeable string; actually asks about your OS not a library; doesn't -- bake in 32bit assumptions that are already false. </rant> -- --
-- isWindows == (os == "mingw32") --isWindows :: Bool -- | Return True on Mac OS X and False otherwise. isMac :: Bool -- | Extra functions for creating processes. Specifically variants that -- automatically check the ExitCode and capture the stdout -- / stderr handles. module System.Process.Extra -- | A version of system that throws an error if the ExitCode -- is not ExitSuccess. system_ :: Partial => String -> IO () -- | A version of system that also captures the output, both -- stdout and stderr. Returns a pair of the ExitCode -- and the output. systemOutput :: String -> IO (ExitCode, String) -- | A version of system that captures the output (both -- stdout and stderr) and throws an error if the -- ExitCode is not ExitSuccess. systemOutput_ :: Partial => String -> IO String -- | Extra functions for working with times. Unlike the other modules in -- this package, there is no corresponding System.Time module. -- This module enhances the functionality from Data.Time.Clock, -- but in quite different ways. -- -- Throughout, time is measured in Seconds, which is a type alias -- for Double. module System.Time.Extra -- | A type alias for seconds, which are stored as Double. type Seconds = Double -- | Sleep for a number of seconds. -- --
-- fmap (round . fst) (duration $ sleep 1) == pure 1 --sleep :: Seconds -> IO () -- | A version of timeout that takes Seconds and never -- overflows the bounds of an Int. In addition, the bug that -- negative timeouts run for ever has been fixed. -- --
-- timeout (-3) (print 1) == pure Nothing -- timeout 0.1 (print 1) == fmap Just (print 1) -- do (t, _) <- duration $ timeout 0.1 $ sleep 1000; print t; pure $ t < 1 -- timeout 0.1 (sleep 2 >> print 1) == pure Nothing --timeout :: Seconds -> IO a -> IO (Maybe a) -- | Show a number of seconds, typically a duration, in a suitable manner -- with reasonable precision for a human. -- --
-- showDuration 3.435 == "3.44s" -- showDuration 623.8 == "10m24s" -- showDuration 62003.8 == "17h13m" -- showDuration 1e8 == "27777h47m" --showDuration :: Seconds -> String -- | Call once to start, then call repeatedly to get the elapsed time since -- the first call. The time is guaranteed to be monotonic. This function -- is robust to system time changes. -- --
-- do f <- offsetTime; xs <- replicateM 10 f; pure $ xs == sort xs --offsetTime :: IO (IO Seconds) -- | A synonym for offsetTime. -- | Deprecated: Use offsetTime instead, which is guaranteed to -- always increase. offsetTimeIncrease :: IO (IO Seconds) -- | Record how long a computation takes in Seconds. -- --
-- do (a,_) <- duration $ sleep 1; pure $ a >= 1 && a <= 1.5 --duration :: IO a -> IO (Seconds, a) instance GHC.Classes.Eq System.Time.Extra.Timeout instance GHC.Show.Show System.Time.Extra.Timeout instance GHC.Exception.Type.Exception System.Time.Extra.Timeout -- | This module documents all the functions available in this package. -- -- Most users should import the specific modules (e.g. -- Data.List.Extra), which also reexport their -- non-Extra modules (e.g. Data.List). -- | Deprecated: This module is provided as documentation of all new -- functions, you should import the more specific modules directly. module Extra -- | On GHC 7.6 and above with the -threaded flag, brackets a call -- to setNumCapabilities. On lower versions (which lack -- setNumCapabilities) this function just runs the argument -- action. withNumCapabilities :: Int -> IO a -> IO a -- | Given an action, produce a wrapped action that runs at most once. If -- the function raises an exception, the same exception will be reraised -- each time. -- --
-- let x ||| y = do t1 <- onceFork x; t2 <- onceFork y; t1; t2 -- \(x :: IO Int) -> void (once x) == pure () -- \(x :: IO Int) -> join (once x) == x -- \(x :: IO Int) -> (do y <- once x; y; y) == x -- \(x :: IO Int) -> (do y <- once x; y ||| y) == x --once :: IO a -> IO (IO a) -- | Like once, but immediately starts running the computation on a -- background thread. -- --
-- \(x :: IO Int) -> join (onceFork x) == x -- \(x :: IO Int) -> (do a <- onceFork x; a; a) == x --onceFork :: IO a -> IO (IO a) -- | Like an MVar, but has no value. Used to guarantee -- single-threaded access, typically to some system resource. As an -- example: -- --
-- lock <- newLock -- let output = withLock . putStrLn -- forkIO $ do ...; output "hello" -- forkIO $ do ...; output "world" ---- -- Here we are creating a lock to ensure that when writing output our -- messages do not get interleaved. This use of MVar never blocks -- on a put. It is permissible, but rare, that a withLock contains a -- withLock inside it - but if so, watch out for deadlocks. data Lock -- | Create a new Lock. newLock :: IO Lock -- | Perform some operation while holding Lock. Will prevent all -- other operations from using the Lock while the action is -- ongoing. withLock :: Lock -> IO a -> IO a -- | Like withLock but will never block. If the operation cannot be -- executed immediately it will return Nothing. withLockTry :: Lock -> IO a -> IO (Maybe a) -- | Like an MVar, but must always be full. Used to operate on a -- mutable variable in a thread-safe way. As an example: -- --
-- hits <- newVar 0
-- forkIO $ do ...; modifyVar_ hits (+1); ...
-- i <- readVar hits
-- print ("HITS",i)
--
--
-- Here we have a variable which we modify atomically, so modifications
-- are not interleaved. This use of MVar never blocks on a put. No
-- modifyVar operation should ever block, and they should always complete
-- in a reasonable timeframe. A Var should not be used to protect
-- some external resource, only the variable contained within.
-- Information from a readVar should not be subsequently inserted
-- back into the Var.
data Var a
-- | Create a new Var with a value.
newVar :: a -> IO (Var a)
-- | Read the current value of the Var.
readVar :: Var a -> IO a
-- | Write a value to become the new value of Var.
writeVar :: Var a -> a -> IO ()
-- | Modify a Var producing a new value and a return result.
modifyVar :: Var a -> (a -> IO (a, b)) -> IO b
-- | Modify a Var, a restricted version of modifyVar.
modifyVar_ :: Var a -> (a -> IO a) -> IO ()
-- | Perform some operation using the value in the Var, a restricted
-- version of modifyVar.
withVar :: Var a -> (a -> IO b) -> IO b
-- | Starts out empty, then is filled exactly once. As an example:
--
-- -- bar <- newBarrier -- forkIO $ do ...; val <- ...; signalBarrier bar val -- print =<< waitBarrier bar ---- -- Here we create a barrier which will contain some computed value. A -- thread is forked to fill the barrier, while the main thread waits for -- it to complete. A barrier has similarities to a future or promise from -- other languages, has been known as an IVar in other Haskell work, and -- in some ways is like a manually managed thunk. data Barrier a -- | Create a new Barrier. newBarrier :: IO (Barrier a) -- | Write a value into the Barrier, releasing anyone at -- waitBarrier. Any subsequent attempts to signal the -- Barrier will throw an exception. signalBarrier :: Partial => Barrier a -> a -> IO () -- | Wait until a barrier has been signaled with signalBarrier. waitBarrier :: Barrier a -> IO a -- | A version of waitBarrier that never blocks, returning -- Nothing if the barrier has not yet been signaled. waitBarrierMaybe :: Barrier a -> IO (Maybe a) -- | A constraint which documents that a function is partial, and on GHC -- 8.0 and above produces a stack trace on failure. For example: -- --
-- myHead :: Partial => [a] -> a -- myHead [] = error "bad" -- myHead (x:xs) = x ---- -- When using Partial with GHC 7.8 or below you need to enable the -- language feature ConstraintKinds, e.g. {-# LANGUAGE -- ConstraintKinds #-} at the top of the file. type Partial = HasCallStack -- | Retry an operation at most n times (n must be positive). -- If the operation fails the nth time it will throw that final -- exception. -- --
-- retry 1 (print "x") == print "x" -- retry 3 (fail "die") == fail "die" --retry :: Int -> IO a -> IO a -- | Retry an operation at most n times (n must be positive), -- while the exception value and type match a predicate. If the operation -- fails the nth time it will throw that final exception. retryBool :: Exception e => (e -> Bool) -> Int -> IO a -> IO a -- | A variant of error that does not produce a stack trace. errorWithoutStackTrace :: () => [Char] -> a -- | Show a value, but if the result contains exceptions, produce -- <Exception>. Defined as stringException . -- show. Particularly useful for printing exceptions to users, -- remembering that exceptions can themselves contain undefined values. showException :: Show e => e -> IO String -- | Fully evaluate an input String. If the String contains embedded -- exceptions it will produce <Exception>. -- --
-- stringException "test" == pure "test"
-- stringException ("test" ++ undefined) == pure "test<Exception>"
-- stringException ("test" ++ undefined ++ "hello") == pure "test<Exception>"
-- stringException ['t','e','s','t',undefined] == pure "test<Exception>"
--
stringException :: String -> IO String
-- | An IO action that when evaluated calls error, in the
-- IO monad. Note that while fail in IO raises an
-- IOException, this function raises an ErrorCall exception
-- with a call stack.
--
-- -- catch (errorIO "Hello") (\(ErrorCall x) -> pure x) == pure "Hello" -- seq (errorIO "foo") (print 1) == print 1 --errorIO :: Partial => String -> IO a -- | Ignore any exceptions thrown by the action. -- --
-- ignore (print 1) == print 1 -- ignore (fail "die") == pure () --ignore :: IO () -> IO () -- | A version of catch without the Exception context, -- restricted to SomeException, so catches all exceptions. catch_ :: IO a -> (SomeException -> IO a) -> IO a -- | Like catch_ but for handle handle_ :: (SomeException -> IO a) -> IO a -> IO a -- | Like catch_ but for try try_ :: IO a -> IO (Either SomeException a) -- | Like catch_ but for catchJust catchJust_ :: (SomeException -> Maybe b) -> IO a -> (b -> IO a) -> IO a -- | Like catch_ but for handleJust handleJust_ :: (SomeException -> Maybe b) -> (b -> IO a) -> IO a -> IO a -- | Like catch_ but for tryJust tryJust_ :: (SomeException -> Maybe b) -> IO a -> IO (Either b a) -- | Catch an exception if the predicate passes, then call the handler with -- the original exception. As an example: -- --
-- readFileExists x == catchBool isDoesNotExistError (readFile "myfile") (const $ pure "") --catchBool :: Exception e => (e -> Bool) -> IO a -> (e -> IO a) -> IO a -- | Like catchBool but for handle. handleBool :: Exception e => (e -> Bool) -> (e -> IO a) -> IO a -> IO a -- | Like catchBool but for try. tryBool :: Exception e => (e -> Bool) -> IO a -> IO (Either e a) -- | Perform some operation on Just, given the field inside the -- Just. -- --
-- whenJust Nothing print == pure () -- whenJust (Just 1) print == print 1 --whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m () -- | Like whenJust, but where the test can be monadic. whenJustM :: Monad m => m (Maybe a) -> (a -> m ()) -> m () -- | Like when, but return either Nothing if the predicate -- was False, of Just with the result of the computation. -- --
-- whenMaybe True (print 1) == fmap Just (print 1) -- whenMaybe False (print 1) == pure Nothing --whenMaybe :: Applicative m => Bool -> m a -> m (Maybe a) -- | Like whenMaybe, but where the test can be monadic. whenMaybeM :: Monad m => m Bool -> m a -> m (Maybe a) -- | The identity function which requires the inner argument to be -- (). Useful for functions with overloaded return types. -- --
-- \(x :: Maybe ()) -> unit x == x --unit :: m () -> m () -- | Monadic generalisation of maybe. maybeM :: Monad m => m b -> (a -> m b) -> m (Maybe a) -> m b -- | Monadic generalisation of fromMaybe. fromMaybeM :: Monad m => m a -> m (Maybe a) -> m a -- | Monadic generalisation of either. eitherM :: Monad m => (a -> m c) -> (b -> m c) -> m (Either a b) -> m c -- | A looping operation, where the predicate returns Left as a seed -- for the next loop or Right to abort the loop. -- --
-- loop (\x -> if x < 10 then Left $ x * 2 else Right $ show x) 1 == "16" --loop :: (a -> Either a b) -> a -> b -- | A monadic version of loop, where the predicate returns -- Left as a seed for the next loop or Right to abort the -- loop. loopM :: Monad m => (a -> m (Either a b)) -> a -> m b -- | Keep running an operation until it becomes False. As an -- example: -- --
-- whileM $ do sleep 0.1; notM $ doesFileExist "foo.txt" -- readFile "foo.txt" ---- -- If you need some state persisted between each test, use loopM. whileM :: Monad m => m Bool -> m () -- | A version of partition that works with a monadic predicate. -- --
-- partitionM (Just . even) [1,2,3] == Just ([2], [1,3]) -- partitionM (const Nothing) [1,2,3] == Nothing --partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a]) -- | A version of concatMap that works with a monadic predicate. concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b] -- | Like concatMapM, but has its arguments flipped, so can be used -- instead of the common fmap concat $ forM pattern. concatForM :: Monad m => [a] -> (a -> m [b]) -> m [b] -- | A version of mconcatMap that works with a monadic predicate. mconcatMapM :: (Monad m, Monoid b) => (a -> m b) -> [a] -> m b -- | A version of mapMaybe that works with a monadic predicate. mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b] -- | Like find, but where the test can be monadic. -- --
-- findM (Just . isUpper) "teST" == Just (Just 'S') -- findM (Just . isUpper) "test" == Just Nothing -- findM (Just . const True) ["x",undefined] == Just (Just "x") --findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) -- | Like findM, but also allows you to compute some additional -- information in the predicate. firstJustM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b) -- | A variant of foldM that has no base case, and thus may only be -- applied to non-empty lists. -- --
-- fold1M (\x y -> Just x) [] == undefined -- fold1M (\x y -> Just $ x + y) [1, 2, 3] == Just 6 --fold1M :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m a -- | Like fold1M but discards the result. fold1M_ :: (Partial, Monad m) => (a -> a -> m a) -> [a] -> m () -- | Like when, but where the test can be monadic. whenM :: Monad m => m Bool -> m () -> m () -- | Like unless, but where the test can be monadic. unlessM :: Monad m => m Bool -> m () -> m () -- | Like if, but where the test can be monadic. ifM :: Monad m => m Bool -> m a -> m a -> m a -- | Like not, but where the test can be monadic. notM :: Functor m => m Bool -> m Bool -- | The lazy || operator lifted to a monad. If the first argument -- evaluates to True the second argument will not be evaluated. -- --
-- Just True ||^ undefined == Just True -- Just False ||^ Just True == Just True -- Just False ||^ Just False == Just False --(||^) :: Monad m => m Bool -> m Bool -> m Bool -- | The lazy && operator lifted to a monad. If the first -- argument evaluates to False the second argument will not be -- evaluated. -- --
-- Just False &&^ undefined == Just False -- Just True &&^ Just True == Just True -- Just True &&^ Just False == Just False --(&&^) :: Monad m => m Bool -> m Bool -> m Bool -- | A version of or lifted to a monad. Retains the short-circuiting -- behaviour. -- --
-- orM [Just False,Just True ,undefined] == Just True -- orM [Just False,Just False,undefined] == undefined -- \xs -> Just (or xs) == orM (map Just xs) --orM :: Monad m => [m Bool] -> m Bool -- | A version of and lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- andM [Just True,Just False,undefined] == Just False -- andM [Just True,Just True ,undefined] == undefined -- \xs -> Just (and xs) == andM (map Just xs) --andM :: Monad m => [m Bool] -> m Bool -- | A version of any lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- anyM Just [False,True ,undefined] == Just True -- anyM Just [False,False,undefined] == undefined -- \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs) --anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool -- | A version of all lifted to a monad. Retains the -- short-circuiting behaviour. -- --
-- allM Just [True,False,undefined] == Just False -- allM Just [True,True ,undefined] == undefined -- \(f :: Int -> Maybe Bool) xs -> anyM f xs == orM (map f xs) --allM :: Monad m => (a -> m Bool) -> [a] -> m Bool -- | Return the contents of a Left-value or a default value -- otherwise. -- --
-- >>> fromLeft 1 (Left 3) -- 3 -- -- >>> fromLeft 1 (Right "foo") -- 1 --fromLeft :: () => a -> Either a b -> a -- | Return the contents of a Right-value or a default value -- otherwise. -- --
-- >>> fromRight 1 (Right 3) -- 3 -- -- >>> fromRight 1 (Left "foo") -- 1 --fromRight :: () => b -> Either a b -> b -- | Pull the value out of an Either where both alternatives have -- the same type. -- --
-- \x -> fromEither (Left x ) == x -- \x -> fromEither (Right x) == x --fromEither :: Either a a -> a -- | The fromLeft' function extracts the element out of a -- Left and throws an error if its argument is Right. Much -- like fromJust, using this function in polished code is -- usually a bad idea. -- --
-- \x -> fromLeft' (Left x) == x -- \x -> fromLeft' (Right x) == undefined --fromLeft' :: Partial => Either l r -> l -- | The fromRight' function extracts the element out of a -- Right and throws an error if its argument is Left. Much -- like fromJust, using this function in polished code is -- usually a bad idea. -- --
-- \x -> fromRight' (Right x) == x -- \x -> fromRight' (Left x) == undefined --fromRight' :: Partial => Either l r -> r -- | Given an Either, convert it to a Maybe, where -- Left becomes Nothing. -- --
-- \x -> eitherToMaybe (Left x) == Nothing -- \x -> eitherToMaybe (Right x) == Just x --eitherToMaybe :: Either a b -> Maybe b -- | Given a Maybe, convert it to an Either, providing a -- suitable value for the Left should the value be Nothing. -- --
-- \a b -> maybeToEither a (Just b) == Right b -- \a -> maybeToEither a Nothing == Left a --maybeToEither :: a -> Maybe b -> Either a b -- | The mapLeft function takes a function and applies it to an -- Either value iff the value takes the form Left _. -- --
-- mapLeft show (Left 1) == Left "1" -- mapLeft show (Right True) == Right True --mapLeft :: (a -> c) -> Either a b -> Either c b -- | The mapRight function takes a function and applies it to an -- Either value iff the value takes the form Right _. -- --
-- mapRight show (Left 1) == Left 1 -- mapRight show (Right True) == Right "True" --mapRight :: (b -> c) -> Either a b -> Either a c -- | Evaluates the value before calling writeIORef. writeIORef' :: IORef a -> a -> IO () -- | Evaluates the value before calling atomicWriteIORef. atomicWriteIORef' :: IORef a -> a -> IO () -- | Variant of atomicModifyIORef which ignores the return value atomicModifyIORef_ :: IORef a -> (a -> a) -> IO () -- | Variant of atomicModifyIORef' which ignores the return value atomicModifyIORef'_ :: IORef a -> (a -> a) -> IO () -- | Convert a string to lower case. -- --
-- lower "This is A TEST" == "this is a test" -- lower "" == "" --lower :: String -> String -- | Convert a string to upper case. -- --
-- upper "This is A TEST" == "THIS IS A TEST" -- upper "" == "" --upper :: String -> String -- | Remove spaces from either side of a string. A combination of -- trimEnd and trimStart. -- --
-- trim " hello " == "hello" -- trimStart " hello " == "hello " -- trimEnd " hello " == " hello" -- \s -> trim s == trimEnd (trimStart s) --trim :: String -> String -- | Remove spaces from the start of a string, see trim. trimStart :: String -> String -- | Remove spaces from the end of a string, see trim. trimEnd :: String -> String -- | Split the first word off a string. Useful for when starting to parse -- the beginning of a string, but you want to accurately preserve -- whitespace in the rest of the string. -- --
-- word1 "" == ("", "")
-- word1 "keyword rest of string" == ("keyword","rest of string")
-- word1 " keyword\n rest of string" == ("keyword","rest of string")
-- \s -> fst (word1 s) == concat (take 1 $ words s)
-- \s -> words (snd $ word1 s) == drop 1 (words s)
--
word1 :: String -> (String, String)
-- | Split the first line off a string.
--
--
-- line1 "" == ("", "")
-- line1 "test" == ("test","")
-- line1 "test\n" == ("test","")
-- line1 "test\nrest" == ("test","rest")
-- line1 "test\nrest\nmore" == ("test","rest\nmore")
--
line1 :: String -> (String, String)
-- | Escape a string such that it can be inserted into an HTML document or
-- " attribute without any special interpretation. This requires
-- escaping the <, >, & and
-- " characters. Note that it will escape " and
-- ' even though that is not required in an HTML body (but is
-- not harmful).
--
-- -- escapeHTML "this is a test" == "this is a test" -- escapeHTML "<b>\"g&t\"</n>" == "<b>"g&t"</n>" -- escapeHTML "t'was another test" == "t'was another test" --escapeHTML :: String -> String -- | Escape a string so it can form part of a JSON literal. This requires -- escaping the special whitespace and control characters. Additionally, -- Note that it does not add quote characters around the string. -- --
-- escapeJSON "this is a test" == "this is a test" -- escapeJSON "\ttab\nnewline\\" == "\\ttab\\nnewline\\\\" -- escapeJSON "\ESC[0mHello" == "\\u001b[0mHello" --escapeJSON :: String -> String -- | Invert of escapeHTML (does not do general HTML unescaping) -- --
-- \xs -> unescapeHTML (escapeHTML xs) == xs --unescapeHTML :: String -> String -- | General JSON unescaping, inversion of escapeJSON and all other -- JSON escapes. -- --
-- \xs -> unescapeJSON (escapeJSON xs) == xs --unescapeJSON :: String -> String -- | Drop a number of elements from the end of the list. -- --
-- dropEnd 3 "hello" == "he" -- dropEnd 5 "bye" == "" -- dropEnd (-1) "bye" == "bye" -- \i xs -> dropEnd i xs `isPrefixOf` xs -- \i xs -> length (dropEnd i xs) == max 0 (length xs - max 0 i) -- \i -> take 3 (dropEnd 5 [i..]) == take 3 [i..] --dropEnd :: Int -> [a] -> [a] -- | Take a number of elements from the end of the list. -- --
-- takeEnd 3 "hello" == "llo" -- takeEnd 5 "bye" == "bye" -- takeEnd (-1) "bye" == "" -- \i xs -> takeEnd i xs `isSuffixOf` xs -- \i xs -> length (takeEnd i xs) == min (max 0 i) (length xs) --takeEnd :: Int -> [a] -> [a] -- | splitAtEnd n xs returns a split where the second -- element tries to contain n elements. -- --
-- splitAtEnd 3 "hello" == ("he","llo")
-- splitAtEnd 3 "he" == ("", "he")
-- \i xs -> uncurry (++) (splitAt i xs) == xs
-- \i xs -> splitAtEnd i xs == (dropEnd i xs, takeEnd i xs)
--
splitAtEnd :: Int -> [a] -> ([a], [a])
-- | Break, but from the end.
--
--
-- breakEnd isLower "youRE" == ("you","RE")
-- breakEnd isLower "youre" == ("youre","")
-- breakEnd isLower "YOURE" == ("","YOURE")
-- \f xs -> breakEnd (not . f) xs == spanEnd f xs
--
breakEnd :: (a -> Bool) -> [a] -> ([a], [a])
-- | Span, but from the end.
--
--
-- spanEnd isUpper "youRE" == ("you","RE")
-- spanEnd (not . isSpace) "x y z" == ("x y ","z")
-- \f xs -> uncurry (++) (spanEnd f xs) == xs
-- \f xs -> spanEnd f xs == swap (both reverse (span f (reverse xs)))
--
spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
-- | A version of dropWhileEnd but with different strictness
-- properties. The function dropWhileEnd can be used on an
-- infinite list and tests the property on each character. In contrast,
-- dropWhileEnd' is strict in the spine of the list but only tests
-- the trailing suffix. This version usually outperforms
-- dropWhileEnd if the list is short or the test is expensive.
-- Note the tests below cover both the prime and non-prime variants.
--
-- -- dropWhileEnd isSpace "ab cde " == "ab cde" -- dropWhileEnd' isSpace "ab cde " == "ab cde" -- last (dropWhileEnd even [undefined,3]) == undefined -- last (dropWhileEnd' even [undefined,3]) == 3 -- head (dropWhileEnd even (3:undefined)) == 3 -- head (dropWhileEnd' even (3:undefined)) == undefined --dropWhileEnd' :: (a -> Bool) -> [a] -> [a] -- | A version of takeWhile operating from the end. -- --
-- takeWhileEnd even [2,3,4,6] == [4,6] --takeWhileEnd :: (a -> Bool) -> [a] -> [a] -- | Return the prefix of the second list if its suffix matches the entire -- first list. -- -- Examples: -- --
-- stripSuffix "bar" "foobar" == Just "foo" -- stripSuffix "" "baz" == Just "baz" -- stripSuffix "foo" "quux" == Nothing --stripSuffix :: Eq a => [a] -> [a] -> Maybe [a] -- | Return the the string before and after the search string, or -- Nothing if the search string is not present. -- -- Examples: -- --
-- stripInfix "::" "a::b::c" == Just ("a", "b::c")
-- stripInfix "/" "foobar" == Nothing
--
stripInfix :: Eq a => [a] -> [a] -> Maybe ([a], [a])
-- | Similar to stripInfix, but searches from the end of the string.
--
--
-- stripInfixEnd "::" "a::b::c" == Just ("a::b", "c")
--
stripInfixEnd :: Eq a => [a] -> [a] -> Maybe ([a], [a])
-- | Drops the given prefix from a list. It returns the original sequence
-- if the sequence doesn't start with the given prefix.
--
-- -- dropPrefix "Mr. " "Mr. Men" == "Men" -- dropPrefix "Mr. " "Dr. Men" == "Dr. Men" --dropPrefix :: Eq a => [a] -> [a] -> [a] -- | Drops the given suffix from a list. It returns the original sequence -- if the sequence doesn't end with the given suffix. -- --
-- dropSuffix "!" "Hello World!" == "Hello World" -- dropSuffix "!" "Hello World!!" == "Hello World!" -- dropSuffix "!" "Hello World." == "Hello World." --dropSuffix :: Eq a => [a] -> [a] -> [a] -- | A variant of words with a custom test. In particular, adjacent -- separators are discarded, as are leading or trailing separators. -- --
-- wordsBy (== ':') "::xyz:abc::123::" == ["xyz","abc","123"] -- \s -> wordsBy isSpace s == words s --wordsBy :: (a -> Bool) -> [a] -> [[a]] -- | A variant of lines with a custom test. In particular, if there -- is a trailing separator it will be discarded. -- --
-- linesBy (== ':') "::xyz:abc::123::" == ["","","xyz","abc","","123",""] -- \s -> linesBy (== '\n') s == lines s -- linesBy (== ';') "my;list;here;" == ["my","list","here"] --linesBy :: (a -> Bool) -> [a] -> [[a]] -- | Find the first instance of needle in haystack. The -- first element of the returned tuple is the prefix of haystack -- before needle is matched. The second is the remainder of -- haystack, starting with the match. If you want the remainder -- without the match, use stripInfix. -- --
-- breakOn "::" "a::b::c" == ("a", "::b::c")
-- breakOn "/" "foobar" == ("foobar", "")
-- \needle haystack -> let (prefix,match) = breakOn needle haystack in prefix ++ match == haystack
--
breakOn :: Eq a => [a] -> [a] -> ([a], [a])
-- | Similar to breakOn, but searches from the end of the string.
--
-- The first element of the returned tuple is the prefix of
-- haystack up to and including the last match of
-- needle. The second is the remainder of haystack,
-- following the match.
--
--
-- breakOnEnd "::" "a::b::c" == ("a::b::", "c")
--
breakOnEnd :: Eq a => [a] -> [a] -> ([a], [a])
-- | Break a list into pieces separated by the first list argument,
-- consuming the delimiter. An empty delimiter is invalid, and will cause
-- an error to be raised.
--
-- -- splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"] -- splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""] -- splitOn "x" "x" == ["",""] -- splitOn "x" "" == [""] -- \s x -> s /= "" ==> intercalate s (splitOn s x) == x -- \c x -> splitOn [c] x == split (==c) x --splitOn :: (Partial, Eq a) => [a] -> [a] -> [[a]] -- | Splits a list into components delimited by separators, where the -- predicate returns True for a separator element. The resulting -- components do not contain the separators. Two adjacent separators -- result in an empty component in the output. -- --
-- split (== 'a') "aabbaca" == ["","","bb","c",""] -- split (== 'a') "" == [""] -- split (== ':') "::xyz:abc::123::" == ["","","xyz","abc","","123","",""] -- split (== ',') "my,list,here" == ["my","list","here"] --split :: (a -> Bool) -> [a] -> [[a]] -- | Split a list into chunks of a given size. The last chunk may contain -- fewer than n elements. The chunk size must be positive. -- --
-- chunksOf 3 "my test" == ["my ","tes","t"] -- chunksOf 3 "mytest" == ["myt","est"] -- chunksOf 8 "" == [] -- chunksOf 0 "test" == undefined --chunksOf :: Partial => Int -> [a] -> [[a]] -- | A total head with a default value. -- --
-- headDef 1 [] == 1 -- headDef 1 [2,3,4] == 2 -- \x xs -> headDef x xs == fromMaybe x (listToMaybe xs) --headDef :: a -> [a] -> a -- | A total last with a default value. -- --
-- lastDef 1 [] == 1 -- lastDef 1 [2,3,4] == 4 -- \x xs -> lastDef x xs == last (x:xs) --lastDef :: a -> [a] -> a -- | A composition of not and null. -- --
-- notNull [] == False -- notNull [1] == True -- \xs -> notNull xs == not (null xs) --notNull :: [a] -> Bool -- | Non-recursive transform over a list, like maybe. -- --
-- list 1 (\v _ -> v - 2) [5,6,7] == 3 -- list 1 (\v _ -> v - 2) [] == 1 -- \nil cons xs -> maybe nil (uncurry cons) (uncons xs) == list nil cons xs --list :: b -> (a -> [a] -> b) -> [a] -> b -- | If the list is empty returns Nothing, otherwise returns the -- init and the last. -- --
-- unsnoc "test" == Just ("tes",'t')
-- unsnoc "" == Nothing
-- \xs -> unsnoc xs == if null xs then Nothing else Just (init xs, last xs)
--
unsnoc :: [a] -> Maybe ([a], a)
-- | Append an element to the start of a list, an alias for '(:)'.
--
-- -- cons 't' "est" == "test" -- \x xs -> uncons (cons x xs) == Just (x,xs) --cons :: a -> [a] -> [a] -- | Append an element to the end of a list, takes O(n) time. -- --
-- snoc "tes" 't' == "test" -- \xs x -> unsnoc (snoc xs x) == Just (xs,x) --snoc :: [a] -> a -> [a] -- | Equivalent to drop 1, but likely to be faster and a single -- lexeme. -- --
-- drop1 "" == "" -- drop1 "test" == "est" -- \xs -> drop 1 xs == drop1 xs --drop1 :: [a] -> [a] -- | Equivalent to dropEnd 1, but likely to be faster and a single -- lexeme. -- --
-- dropEnd1 "" == "" -- dropEnd1 "test" == "tes" -- \xs -> dropEnd 1 xs == dropEnd1 xs --dropEnd1 :: [a] -> [a] -- | Version on concatMap generalised to a Monoid rather than -- just a list. -- --
-- mconcatMap Sum [1,2,3] == Sum 6 -- \f xs -> mconcatMap f xs == concatMap f xs --mconcatMap :: Monoid b => (a -> b) -> [a] -> b -- | Enumerate all the values of an Enum, from minBound to -- maxBound. -- --
-- enumerate == [False, True] --enumerate :: (Enum a, Bounded a) => [a] -- | A combination of group and sort. -- --
-- groupSort [(1,'t'),(3,'t'),(2,'e'),(2,'s')] == [(1,"t"),(2,"es"),(3,"t")] -- \xs -> map fst (groupSort xs) == sort (nub (map fst xs)) -- \xs -> concatMap snd (groupSort xs) == map snd (sortOn fst xs) --groupSort :: Ord k => [(k, v)] -> [(k, [v])] -- | A combination of group and sort, using a part of the -- value to compare on. -- --
-- groupSortOn length ["test","of","sized","item"] == [["of"],["test","item"],["sized"]] --groupSortOn :: Ord b => (a -> b) -> [a] -> [[a]] -- | A combination of group and sort, using a predicate to -- compare on. -- --
-- groupSortBy (compare `on` length) ["test","of","sized","item"] == [["of"],["test","item"],["sized"]] --groupSortBy :: (a -> a -> Ordering) -> [a] -> [[a]] -- | O(n log n). The nubOrd function removes duplicate -- elements from a list. In particular, it keeps only the first -- occurrence of each element. Unlike the standard nub operator, -- this version requires an Ord instance and consequently runs -- asymptotically faster. -- --
-- nubOrd "this is a test" == "this ae"
-- nubOrd (take 4 ("this" ++ undefined)) == "this"
-- \xs -> nubOrd xs == nub xs
--
nubOrd :: Ord a => [a] -> [a]
-- | A version of nubOrd with a custom predicate.
--
-- -- nubOrdBy (compare `on` length) ["a","test","of","this"] == ["a","test","of"] --nubOrdBy :: (a -> a -> Ordering) -> [a] -> [a] -- | A version of nubOrd which operates on a portion of the value. -- --
-- nubOrdOn length ["a","test","of","this"] == ["a","test","of"] --nubOrdOn :: Ord b => (a -> b) -> [a] -> [a] -- | DEPRECATED Use nubOrdOn, since this function is -- _O(n^2)_. -- -- A version of nub where the equality is done on some extracted -- value. nubOn f is equivalent to nubBy ((==) on -- f), but has the performance advantage of only evaluating -- f once for each element in the input list. -- | Deprecated: Use nubOrdOn, since this function is O(n^2) nubOn :: Eq b => (a -> b) -> [a] -> [a] -- | A version of group where the equality is done on some extracted -- value. groupOn :: Eq b => (a -> b) -> [a] -> [[a]] -- | O(n log n). The nubSort function sorts and removes -- duplicate elements from a list. In particular, it keeps only the first -- occurrence of each element. -- --
-- nubSort "this is a test" == " aehist" -- \xs -> nubSort xs == nub (sort xs) --nubSort :: Ord a => [a] -> [a] -- | A version of nubSort with a custom predicate. -- --
-- nubSortBy (compare `on` length) ["a","test","of","this"] == ["a","of","test"] --nubSortBy :: (a -> a -> Ordering) -> [a] -> [a] -- | A version of nubSort which operates on a portion of the value. -- --
-- nubSortOn length ["a","test","of","this"] == ["a","of","test"] --nubSortOn :: Ord b => (a -> b) -> [a] -> [a] -- | A version of maximum where the comparison is done on some -- extracted value. Raises an error if the list is empty. Only calls the -- function once per element. -- --
-- maximumOn id [] == undefined -- maximumOn length ["test","extra","a"] == "extra" --maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a -- | A version of minimum where the comparison is done on some -- extracted value. Raises an error if the list is empty. Only calls the -- function once per element. -- --
-- minimumOn id [] == undefined -- minimumOn length ["test","extra","a"] == "a" --minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a -- | Are two lists disjoint, with no elements in common. -- --
-- disjoint [1,2,3] [4,5] == True -- disjoint [1,2,3] [4,1] == False --disjoint :: Eq a => [a] -> [a] -> Bool -- | Are all elements the same. -- --
-- allSame [1,1,2] == False -- allSame [1,1,1] == True -- allSame [1] == True -- allSame [] == True -- allSame (1:1:2:undefined) == False -- \xs -> allSame xs == (length (nub xs) <= 1) --allSame :: Eq a => [a] -> Bool -- | Is there any element which occurs more than once. -- --
-- anySame [1,1,2] == True -- anySame [1,2,3] == False -- anySame (1:2:1:undefined) == True -- anySame [] == False -- \xs -> anySame xs == (length (nub xs) < length xs) --anySame :: Eq a => [a] -> Bool -- | Apply some operation repeatedly, producing an element of output and -- the remainder of the list. -- --
-- \xs -> repeatedly (splitAt 3) xs == chunksOf 3 xs -- \xs -> repeatedly word1 (trim xs) == words xs -- \xs -> repeatedly line1 xs == lines xs --repeatedly :: ([a] -> (b, [a])) -> [a] -> [b] -- | Find the first element of a list for which the operation returns -- Just, along with the result of the operation. Like find -- but useful where the function also computes some expensive information -- that can be reused. Particular useful when the function is monadic, -- see firstJustM. -- --
-- firstJust id [Nothing,Just 3] == Just 3 -- firstJust id [Nothing,Nothing] == Nothing --firstJust :: (a -> Maybe b) -> [a] -> Maybe b -- | A merging of unzip and concat. -- --
-- concatUnzip [("a","AB"),("bc","C")] == ("abc","ABC")
--
concatUnzip :: [([a], [b])] -> ([a], [b])
-- | A merging of unzip3 and concat.
--
--
-- concatUnzip3 [("a","AB",""),("bc","C","123")] == ("abc","ABC","123")
--
concatUnzip3 :: [([a], [b], [c])] -> ([a], [b], [c])
-- | zip against an enumeration. Never truncates the output - raises
-- an error if the enumeration runs out.
--
-- -- \i xs -> zip [i..] xs == zipFrom i xs -- zipFrom False [1..3] == [(False,1),(True, 2)] --zipFrom :: Enum a => a -> [b] -> [(a, b)] -- | zipFrom generalised to any combining operation. Never truncates -- the output - raises an error if the enumeration runs out. -- --
-- \i xs -> zipWithFrom (,) i xs == zipFrom i xs --zipWithFrom :: Enum a => (a -> b -> c) -> a -> [b] -> [c] -- | Replace a subsequence everywhere it occurs. The first argument must -- not be the empty list. -- --
-- replace "el" "_" "Hello Bella" == "H_lo B_la" -- replace "el" "e" "Hello" == "Helo" -- replace "" "e" "Hello" == undefined -- \xs ys -> not (null xs) ==> replace xs xs ys == ys --replace :: (Partial, Eq a) => [a] -> [a] -> [a] -> [a] -- | Merge two lists which are assumed to be ordered. -- --
-- merge "ace" "bd" == "abcde" -- \xs ys -> merge (sort xs) (sort ys) == sort (xs ++ ys) --merge :: Ord a => [a] -> [a] -> [a] -- | Like merge, but with a custom ordering function. mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a] -- | O(n). Append an element to a list. -- --
-- [1,2,3] |: 4 |> 5 == 1 :| [2,3,4,5] --(|:) :: [a] -> a -> NonEmpty a infixl 5 |: -- | O(n). Append an element to a non-empty list. -- --
-- (1 :| [2,3]) |> 4 |> 5 == 1 :| [2,3,4,5] --(|>) :: NonEmpty a -> a -> NonEmpty a infixl 5 |> -- | Append a list to a non-empty list. -- --
-- appendl (1 :| [2,3]) [4,5] == 1 :| [2,3,4,5] --appendl :: NonEmpty a -> [a] -> NonEmpty a -- | Append a non-empty list to a list. -- --
-- appendr [1,2,3] (4 :| [5]) == 1 :| [2,3,4,5] --appendr :: [a] -> NonEmpty a -> NonEmpty a -- | The largest element of a non-empty list. maximum1 :: Ord a => NonEmpty a -> a -- | The least element of a non-empty list. minimum1 :: Ord a => NonEmpty a -> a -- | The largest element of a non-empty list with respect to the given -- comparison function. maximumBy1 :: (a -> a -> Ordering) -> NonEmpty a -> a -- | The least element of a non-empty list with respect to the given -- comparison function. minimumBy1 :: (a -> a -> Ordering) -> NonEmpty a -> a -- | A version of maximum1 where the comparison is done on some -- extracted value. maximumOn1 :: Ord b => (a -> b) -> NonEmpty a -> a -- | A version of minimum1 where the comparison is done on some -- extracted value. minimumOn1 :: Ord b => (a -> b) -> NonEmpty a -> a -- | Update the first component of a pair. -- --
-- first succ (1,"test") == (2,"test") --first :: (a -> a') -> (a, b) -> (a', b) -- | Update the second component of a pair. -- --
-- second reverse (1,"test") == (1,"tset") --second :: (b -> b') -> (a, b) -> (a, b') -- | Given two functions, apply one to the first component and one to the -- second. A specialised version of ***. -- --
-- (succ *** reverse) (1,"test") == (2,"tset") --(***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') infixr 3 *** -- | Given two functions, apply both to a single argument to form a pair. A -- specialised version of &&&. -- --
-- (succ &&& pred) 1 == (2,0) --(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) infixr 3 &&& -- | Duplicate a single value into a pair. -- --
-- dupe 12 == (12, 12) --dupe :: a -> (a, a) -- | Apply a single function to both components of a pair. -- --
-- both succ (1,2) == (2,3) --both :: (a -> b) -> (a, a) -> (b, b) -- | Update the first component of a pair. -- --
-- firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")] --firstM :: Functor m => (a -> m a') -> (a, b) -> m (a', b) -- | Update the second component of a pair. -- --
-- secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")] --secondM :: Functor m => (b -> m b') -> (a, b) -> m (a, b') -- | Extract the fst of a triple. fst3 :: (a, b, c) -> a -- | Extract the snd of a triple. snd3 :: (a, b, c) -> b -- | Extract the final element of a triple. thd3 :: (a, b, c) -> c -- | Converts an uncurried function to a curried function. curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d -- | Converts a curried function to a function on a triple. uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d -- | Read a Version or throw an exception. -- --
-- \x -> readVersion (showVersion x) == x -- readVersion "hello" == undefined --readVersion :: Partial => String -> Version -- | Show a number to a fixed number of decimal places. -- --
-- showDP 4 pi == "3.1416" -- showDP 0 pi == "3" -- showDP 2 3 == "3.00" --showDP :: RealFloat a => Int -> a -> String -- | Specialised numeric conversion, type restricted version of -- fromIntegral. intToDouble :: Int -> Double -- | Specialised numeric conversion, type restricted version of -- fromIntegral. intToFloat :: Int -> Float -- | Specialised numeric conversion, type restricted version of -- realToFrac. floatToDouble :: Float -> Double -- | Specialised numeric conversion, type restricted version of -- realToFrac. doubleToFloat :: Double -> Float -- | Run an IO action with the given working directory and restore -- the original working directory afterwards, even if the given action -- fails due to an exception. -- -- The operation may fail with the same exceptions as -- getCurrentDirectory and setCurrentDirectory. withCurrentDirectory :: () => FilePath -> IO a -> IO a -- | Create a directory with permissions so that only the current user can -- view it. On Windows this function is equivalent to -- createDirectory. createDirectoryPrivate :: String -> IO () -- | List the files and directories directly within a directory. Each -- result will be prefixed by the query directory, and the special -- directories . and .. will be ignored. Intended as a -- cleaned up version of getDirectoryContents. -- --
-- withTempDir $ \dir -> do writeFile (dir </> "test.txt") ""; (== [dir </> "test.txt"]) <$> listContents dir -- let touch = mapM_ $ \x -> createDirectoryIfMissing True (takeDirectory x) >> writeFile x "" -- let listTest op as bs = withTempDir $ \dir -> do touch $ map (dir </>) as; res <- op dir; pure $ map (drop (length dir + 1)) res == bs -- listTest listContents ["bar.txt","foo/baz.txt","zoo"] ["bar.txt","foo","zoo"] --listContents :: FilePath -> IO [FilePath] -- | Like listContents, but only returns the directories in a -- directory, not the files. Each directory will be prefixed by the query -- directory. -- --
-- listTest listDirectories ["bar.txt","foo/baz.txt","zoo"] ["foo"] --listDirectories :: FilePath -> IO [FilePath] -- | Like listContents, but only returns the files in a directory, -- not other directories. Each file will be prefixed by the query -- directory. -- --
-- listTest listFiles ["bar.txt","foo/baz.txt","zoo"] ["bar.txt","zoo"] --listFiles :: FilePath -> IO [FilePath] -- | Like listFilesRecursive, but with a predicate to decide where -- to recurse into. Typically directories starting with . would -- be ignored. The initial argument directory will have the test applied -- to it. -- --
-- listTest (listFilesInside $ pure . not . isPrefixOf "." . takeFileName) -- ["bar.txt","foo" </> "baz.txt",".foo" </> "baz2.txt", "zoo"] ["bar.txt","zoo","foo" </> "baz.txt"] -- listTest (listFilesInside $ const $ pure False) ["bar.txt"] [] --listFilesInside :: (FilePath -> IO Bool) -> FilePath -> IO [FilePath] -- | Like listFiles, but goes recursively through all -- subdirectories. This function will follow symlinks, and if they form a -- loop, this function will not terminate. -- --
-- listTest listFilesRecursive ["bar.txt","zoo","foo" </> "baz.txt"] ["bar.txt","zoo","foo" </> "baz.txt"] --listFilesRecursive :: FilePath -> IO [FilePath] -- | Return True on Windows and False otherwise. A runtime -- version of #ifdef minw32_HOST_OS. Equivalent to os == -- "mingw32", but: more efficient; doesn't require typing an easily -- mistypeable string; actually asks about your OS not a library; doesn't -- bake in 32bit assumptions that are already false. </rant> -- --
-- isWindows == (os == "mingw32") --isWindows :: Bool -- | Return True on Mac OS X and False otherwise. isMac :: Bool -- | Capture the stdout and stderr of a computation. -- --
-- captureOutput (print 1) == pure ("1\n",())
--
captureOutput :: IO a -> IO (String, a)
-- | Execute an action with a custom BufferMode, a wrapper around
-- hSetBuffering.
withBuffering :: Handle -> BufferMode -> IO a -> IO a
-- | Like readFile, but setting an encoding.
readFileEncoding :: TextEncoding -> FilePath -> IO String
-- | Like readFile, but with the encoding utf8.
readFileUTF8 :: FilePath -> IO String
-- | Like readFile, but for binary files.
readFileBinary :: FilePath -> IO String
-- | A strict version of readFile. When the string is produced, the
-- entire file will have been read into memory and the file handle will
-- have been closed. Closing the file handle does not rely on the garbage
-- collector.
--
-- -- \(filter isHexDigit -> s) -> fmap (== s) $ withTempFile $ \file -> do writeFile file s; readFile' file --readFile' :: FilePath -> IO String -- | A strict version of readFileEncoding, see readFile' for -- details. readFileEncoding' :: TextEncoding -> FilePath -> IO String -- | A strict version of readFileUTF8, see readFile' for -- details. readFileUTF8' :: FilePath -> IO String -- | A strict version of readFileBinary, see readFile' for -- details. readFileBinary' :: FilePath -> IO String -- | Write a file with a particular encoding. writeFileEncoding :: TextEncoding -> FilePath -> String -> IO () -- | Write a file with the utf8 encoding. -- --
-- \s -> withTempFile $ \file -> do writeFileUTF8 file s; fmap (== s) $ readFileUTF8' file --writeFileUTF8 :: FilePath -> String -> IO () -- | Write a binary file. -- --
-- \(ASCIIString s) -> withTempFile $ \file -> do writeFileBinary file s; fmap (== s) $ readFileBinary' file --writeFileBinary :: FilePath -> String -> IO () -- | Create a temporary file in the temporary directory. The file will be -- deleted after the action completes (provided the file is not still -- open). The FilePath will not have any file extension, will -- exist, and will be zero bytes long. If you require a file with a -- specific name, use withTempDir. -- --
-- withTempFile doesFileExist == pure True -- (doesFileExist =<< withTempFile pure) == pure False -- withTempFile readFile' == pure "" --withTempFile :: (FilePath -> IO a) -> IO a -- | Create a temporary directory inside the system temporary directory. -- The directory will be deleted after the action completes. -- --
-- withTempDir doesDirectoryExist == pure True -- (doesDirectoryExist =<< withTempDir pure) == pure False -- withTempDir listFiles == pure [] --withTempDir :: (FilePath -> IO a) -> IO a -- | Provide a function to create a temporary file, and a way to delete a -- temporary file. Most users should use withTempFile which -- combines these operations. newTempFile :: IO (FilePath, IO ()) -- | Provide a function to create a temporary directory, and a way to -- delete a temporary directory. Most users should use withTempDir -- which combines these operations. newTempDir :: IO (FilePath, IO ()) -- | Like newTempFile but using a custom temporary directory. newTempFileWithin :: FilePath -> IO (FilePath, IO ()) -- | Like newTempDir but using a custom temporary directory. newTempDirWithin :: FilePath -> IO (FilePath, IO ()) -- | Returns True if both files have the same content. Raises an -- error if either file is missing. -- --
-- fileEq "does_not_exist1" "does_not_exist2" == undefined -- fileEq "does_not_exist" "does_not_exist" == undefined -- withTempFile $ \f1 -> fileEq "does_not_exist" f1 == undefined -- withTempFile $ \f1 -> withTempFile $ \f2 -> fileEq f1 f2 -- withTempFile $ \f1 -> withTempFile $ \f2 -> writeFile f1 "a" >> writeFile f2 "a" >> fileEq f1 f2 -- withTempFile $ \f1 -> withTempFile $ \f2 -> writeFile f1 "a" >> writeFile f2 "b" >> notM (fileEq f1 f2) --fileEq :: FilePath -> FilePath -> IO Bool -- | A version of system that throws an error if the ExitCode -- is not ExitSuccess. system_ :: Partial => String -> IO () -- | A version of system that also captures the output, both -- stdout and stderr. Returns a pair of the ExitCode -- and the output. systemOutput :: String -> IO (ExitCode, String) -- | A version of system that captures the output (both -- stdout and stderr) and throws an error if the -- ExitCode is not ExitSuccess. systemOutput_ :: Partial => String -> IO String -- | A type alias for seconds, which are stored as Double. type Seconds = Double -- | Sleep for a number of seconds. -- --
-- fmap (round . fst) (duration $ sleep 1) == pure 1 --sleep :: Seconds -> IO () -- | A version of timeout that takes Seconds and never -- overflows the bounds of an Int. In addition, the bug that -- negative timeouts run for ever has been fixed. -- --
-- timeout (-3) (print 1) == pure Nothing -- timeout 0.1 (print 1) == fmap Just (print 1) -- do (t, _) <- duration $ timeout 0.1 $ sleep 1000; print t; pure $ t < 1 -- timeout 0.1 (sleep 2 >> print 1) == pure Nothing --timeout :: Seconds -> IO a -> IO (Maybe a) -- | Show a number of seconds, typically a duration, in a suitable manner -- with reasonable precision for a human. -- --
-- showDuration 3.435 == "3.44s" -- showDuration 623.8 == "10m24s" -- showDuration 62003.8 == "17h13m" -- showDuration 1e8 == "27777h47m" --showDuration :: Seconds -> String -- | Call once to start, then call repeatedly to get the elapsed time since -- the first call. The time is guaranteed to be monotonic. This function -- is robust to system time changes. -- --
-- do f <- offsetTime; xs <- replicateM 10 f; pure $ xs == sort xs --offsetTime :: IO (IO Seconds) -- | A synonym for offsetTime. -- | Deprecated: Use offsetTime instead, which is guaranteed to -- always increase. offsetTimeIncrease :: IO (IO Seconds) -- | Record how long a computation takes in Seconds. -- --
-- do (a,_) <- duration $ sleep 1; pure $ a >= 1 && a <= 1.5 --duration :: IO a -> IO (Seconds, a) -- | This module provides Text.Read with functions added in later -- versions. -- -- Currently this module has no functionality beyond Text.Read. module Text.Read.Extra