{-# LANGUAGE Trustworthy #-}
module Futhark.Util
( nubOrd,
nubByOrd,
mapAccumLM,
maxinum,
chunk,
chunks,
pairs,
unpairs,
dropAt,
takeLast,
dropLast,
mapEither,
maybeNth,
maybeHead,
splitFromEnd,
splitAt3,
focusNth,
hashText,
unixEnvironment,
isEnvVarAtLeast,
startupTime,
fancyTerminal,
runProgramWithExitCode,
directoryContents,
roundFloat,
ceilFloat,
floorFloat,
roundDouble,
ceilDouble,
floorDouble,
lgamma,
lgammaf,
tgamma,
tgammaf,
erf,
erff,
erfc,
erfcf,
cbrt,
cbrtf,
hypot,
hypotf,
fromPOSIX,
toPOSIX,
trim,
pmapIO,
interactWithFileSafely,
convFloat,
UserString,
EncodedString,
zEncodeString,
atMostChars,
invertMap,
traverseFold,
fixPoint,
)
where
import Control.Arrow (first)
import Control.Concurrent
import Control.Exception
import Control.Monad
import Crypto.Hash.MD5 as MD5
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base16 as Base16
import Data.Char
import Data.Either
import Data.Foldable (fold)
import Data.Function ((&))
import Data.List (foldl', genericDrop, genericSplitAt, sortBy)
import qualified Data.List.NonEmpty as NE
import qualified Data.Map as M
import Data.Maybe
import qualified Data.Set as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Encoding.Error as T
import Data.Time.Clock (UTCTime, getCurrentTime)
import Data.Tuple (swap)
import Numeric
import qualified System.Directory.Tree as Dir
import System.Environment
import System.Exit
import qualified System.FilePath as Native
import qualified System.FilePath.Posix as Posix
import System.IO (hIsTerminalDevice, stdout)
import System.IO.Error (isDoesNotExistError)
import System.IO.Unsafe
import System.Process.ByteString
import Text.Read (readMaybe)
nubOrd :: Ord a => [a] -> [a]
nubOrd :: [a] -> [a]
nubOrd = (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
nubByOrd a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare
nubByOrd :: (a -> a -> Ordering) -> [a] -> [a]
nubByOrd :: (a -> a -> Ordering) -> [a] -> [a]
nubByOrd a -> a -> Ordering
cmp = (NonEmpty a -> a) -> [NonEmpty a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map NonEmpty a -> a
forall a. NonEmpty a -> a
NE.head ([NonEmpty a] -> [a]) -> ([a] -> [NonEmpty a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Bool) -> [a] -> [NonEmpty a]
forall (f :: * -> *) a.
Foldable f =>
(a -> a -> Bool) -> f a -> [NonEmpty a]
NE.groupBy a -> a -> Bool
eq ([a] -> [NonEmpty a]) -> ([a] -> [a]) -> [a] -> [NonEmpty a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy a -> a -> Ordering
cmp
where
eq :: a -> a -> Bool
eq a
x a
y = a -> a -> Ordering
cmp a
x a
y Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ
mapAccumLM ::
Monad m =>
(acc -> x -> m (acc, y)) ->
acc ->
[x] ->
m (acc, [y])
mapAccumLM :: (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM acc -> x -> m (acc, y)
_ acc
acc [] = (acc, [y]) -> m (acc, [y])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (acc
acc, [])
mapAccumLM acc -> x -> m (acc, y)
f acc
acc (x
x : [x]
xs) = do
(acc
acc', y
x') <- acc -> x -> m (acc, y)
f acc
acc x
x
(acc
acc'', [y]
xs') <- (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM acc -> x -> m (acc, y)
f acc
acc' [x]
xs
(acc, [y]) -> m (acc, [y])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (acc
acc'', y
x' y -> [y] -> [y]
forall a. a -> [a] -> [a]
: [y]
xs')
chunk :: Int -> [a] -> [[a]]
chunk :: Int -> [a] -> [[a]]
chunk Int
_ [] = []
chunk Int
n [a]
xs =
let ([a]
bef, [a]
aft) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n [a]
xs
in [a]
bef [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: Int -> [a] -> [[a]]
forall a. Int -> [a] -> [[a]]
chunk Int
n [a]
aft
chunks :: [Int] -> [a] -> [[a]]
chunks :: [Int] -> [a] -> [[a]]
chunks [] [a]
_ = []
chunks (Int
n : [Int]
ns) [a]
xs =
let ([a]
bef, [a]
aft) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n [a]
xs
in [a]
bef [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [Int] -> [a] -> [[a]]
forall a. [Int] -> [a] -> [[a]]
chunks [Int]
ns [a]
aft
pairs :: [a] -> [(a, a)]
pairs :: [a] -> [(a, a)]
pairs (a
a : a
b : [a]
l) = (a
a, a
b) (a, a) -> [(a, a)] -> [(a, a)]
forall a. a -> [a] -> [a]
: [a] -> [(a, a)]
forall a. [a] -> [(a, a)]
pairs [a]
l
pairs [a]
_ = []
unpairs :: [(a, a)] -> [a]
unpairs :: [(a, a)] -> [a]
unpairs [] = []
unpairs ((a
a, a
b) : [(a, a)]
l) = a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
b a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [(a, a)] -> [a]
forall a. [(a, a)] -> [a]
unpairs [(a, a)]
l
maxinum :: (Num a, Ord a, Foldable f) => f a -> a
maxinum :: f a -> a
maxinum = (a -> a -> a) -> a -> f a -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' a -> a -> a
forall a. Ord a => a -> a -> a
max a
0
dropAt :: Int -> Int -> [a] -> [a]
dropAt :: Int -> Int -> [a] -> [a]
dropAt Int
i Int
n [a]
xs = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
i [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n) [a]
xs
takeLast :: Int -> [a] -> [a]
takeLast :: Int -> [a] -> [a]
takeLast Int
n = [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
n ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. [a] -> [a]
reverse
dropLast :: Int -> [a] -> [a]
dropLast :: Int -> [a] -> [a]
dropLast Int
n = [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
n ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. [a] -> [a]
reverse
mapEither :: (a -> Either b c) -> [a] -> ([b], [c])
mapEither :: (a -> Either b c) -> [a] -> ([b], [c])
mapEither a -> Either b c
f [a]
l = [Either b c] -> ([b], [c])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ([Either b c] -> ([b], [c])) -> [Either b c] -> ([b], [c])
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> [a] -> [Either b c]
forall a b. (a -> b) -> [a] -> [b]
map a -> Either b c
f [a]
l
maybeNth :: Integral int => int -> [a] -> Maybe a
maybeNth :: int -> [a] -> Maybe a
maybeNth int
i [a]
l
| int
i int -> int -> Bool
forall a. Ord a => a -> a -> Bool
>= int
0, a
v : [a]
_ <- int -> [a] -> [a]
forall i a. Integral i => i -> [a] -> [a]
genericDrop int
i [a]
l = a -> Maybe a
forall a. a -> Maybe a
Just a
v
| Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
maybeHead :: [a] -> Maybe a
maybeHead :: [a] -> Maybe a
maybeHead [] = Maybe a
forall a. Maybe a
Nothing
maybeHead (a
x : [a]
_) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
splitFromEnd :: Int -> [a] -> ([a], [a])
splitFromEnd :: Int -> [a] -> ([a], [a])
splitFromEnd Int
i [a]
l = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) [a]
l
splitAt3 :: Int -> Int -> [a] -> ([a], [a], [a])
splitAt3 :: Int -> Int -> [a] -> ([a], [a], [a])
splitAt3 Int
n Int
m [a]
l =
let ([a]
xs, [a]
l') = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n [a]
l
([a]
ys, [a]
zs) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
m [a]
l'
in ([a]
xs, [a]
ys, [a]
zs)
focusNth :: Integral int => int -> [a] -> Maybe ([a], a, [a])
focusNth :: int -> [a] -> Maybe ([a], a, [a])
focusNth int
i [a]
xs
| ([a]
bef, a
x : [a]
aft) <- int -> [a] -> ([a], [a])
forall i a. Integral i => i -> [a] -> ([a], [a])
genericSplitAt int
i [a]
xs = ([a], a, [a]) -> Maybe ([a], a, [a])
forall a. a -> Maybe a
Just ([a]
bef, a
x, [a]
aft)
| Bool
otherwise = Maybe ([a], a, [a])
forall a. Maybe a
Nothing
hashText :: T.Text -> T.Text
hashText :: Text -> Text
hashText =
OnDecodeError -> ByteString -> Text
T.decodeUtf8With OnDecodeError
T.lenientDecode (ByteString -> Text) -> (Text -> ByteString) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base16.encode (ByteString -> ByteString)
-> (Text -> ByteString) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
MD5.hash (ByteString -> ByteString)
-> (Text -> ByteString) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8
{-# NOINLINE unixEnvironment #-}
unixEnvironment :: [(String, String)]
unixEnvironment :: [(String, String)]
unixEnvironment = IO [(String, String)] -> [(String, String)]
forall a. IO a -> a
unsafePerformIO IO [(String, String)]
getEnvironment
isEnvVarAtLeast :: String -> Int -> Bool
isEnvVarAtLeast :: String -> Int -> Bool
isEnvVarAtLeast String
s Int
x =
case String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (String -> Maybe Int) -> Maybe String -> Maybe Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
s [(String, String)]
unixEnvironment of
Just Int
y -> Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
x
Maybe Int
_ -> Bool
False
{-# NOINLINE startupTime #-}
startupTime :: UTCTime
startupTime :: UTCTime
startupTime = IO UTCTime -> UTCTime
forall a. IO a -> a
unsafePerformIO IO UTCTime
getCurrentTime
{-# NOINLINE fancyTerminal #-}
fancyTerminal :: Bool
fancyTerminal :: Bool
fancyTerminal = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
Bool
isTTY <- Handle -> IO Bool
hIsTerminalDevice Handle
stdout
Bool
isDumb <- (String -> Maybe String
forall a. a -> Maybe a
Just String
"dumb" Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
==) (Maybe String -> Bool) -> IO (Maybe String) -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO (Maybe String)
lookupEnv String
"TERM"
Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Bool
isTTY Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
isDumb
runProgramWithExitCode ::
FilePath ->
[String] ->
BS.ByteString ->
IO (Either IOException (ExitCode, String, String))
runProgramWithExitCode :: String
-> [String]
-> ByteString
-> IO (Either IOException (ExitCode, String, String))
runProgramWithExitCode String
exe [String]
args ByteString
inp =
((ExitCode, String, String)
-> Either IOException (ExitCode, String, String)
forall a b. b -> Either a b
Right ((ExitCode, String, String)
-> Either IOException (ExitCode, String, String))
-> ((ExitCode, ByteString, ByteString)
-> (ExitCode, String, String))
-> (ExitCode, ByteString, ByteString)
-> Either IOException (ExitCode, String, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ExitCode, ByteString, ByteString) -> (ExitCode, String, String)
forall a. (a, ByteString, ByteString) -> (a, String, String)
postprocess ((ExitCode, ByteString, ByteString)
-> Either IOException (ExitCode, String, String))
-> IO (ExitCode, ByteString, ByteString)
-> IO (Either IOException (ExitCode, String, String))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
readProcessWithExitCode String
exe [String]
args ByteString
inp)
IO (Either IOException (ExitCode, String, String))
-> (IOException
-> IO (Either IOException (ExitCode, String, String)))
-> IO (Either IOException (ExitCode, String, String))
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \IOException
e -> Either IOException (ExitCode, String, String)
-> IO (Either IOException (ExitCode, String, String))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IOException -> Either IOException (ExitCode, String, String)
forall a b. a -> Either a b
Left IOException
e)
where
decode :: ByteString -> String
decode = Text -> String
T.unpack (Text -> String) -> (ByteString -> Text) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OnDecodeError -> ByteString -> Text
T.decodeUtf8With OnDecodeError
T.lenientDecode
postprocess :: (a, ByteString, ByteString) -> (a, String, String)
postprocess (a
code, ByteString
out, ByteString
err) =
(a
code, ByteString -> String
decode ByteString
out, ByteString -> String
decode ByteString
err)
directoryContents :: FilePath -> IO [FilePath]
directoryContents :: String -> IO [String]
directoryContents String
dir = do
String
_ Dir.:/ DirTree String
tree <- (String -> IO String) -> String -> IO (AnchoredDirTree String)
forall a. (String -> IO a) -> String -> IO (AnchoredDirTree a)
Dir.readDirectoryWith String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
dir
case DirTree String -> [DirTree String]
forall a. DirTree a -> [DirTree a]
Dir.failures DirTree String
tree of
Dir.Failed String
_ IOException
err : [DirTree String]
_ -> IOException -> IO [String]
forall a e. Exception e => e -> a
throw IOException
err
[DirTree String]
_ -> [String] -> IO [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([String] -> IO [String]) -> [String] -> IO [String]
forall a b. (a -> b) -> a -> b
$ (DirTree String -> Maybe String) -> [DirTree String] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DirTree String -> Maybe String
forall a. DirTree a -> Maybe a
isFile ([DirTree String] -> [String]) -> [DirTree String] -> [String]
forall a b. (a -> b) -> a -> b
$ DirTree String -> [DirTree String]
forall a. DirTree a -> [DirTree a]
Dir.flattenDir DirTree String
tree
where
isFile :: DirTree a -> Maybe a
isFile (Dir.File String
_ a
path) = a -> Maybe a
forall a. a -> Maybe a
Just a
path
isFile DirTree a
_ = Maybe a
forall a. Maybe a
Nothing
foreign import ccall "nearbyint" c_nearbyint :: Double -> Double
foreign import ccall "nearbyintf" c_nearbyintf :: Float -> Float
foreign import ccall "ceil" c_ceil :: Double -> Double
foreign import ccall "ceilf" c_ceilf :: Float -> Float
foreign import ccall "floor" c_floor :: Double -> Double
foreign import ccall "floorf" c_floorf :: Float -> Float
roundFloat :: Float -> Float
roundFloat :: Float -> Float
roundFloat = Float -> Float
c_nearbyintf
ceilFloat :: Float -> Float
ceilFloat :: Float -> Float
ceilFloat = Float -> Float
c_ceilf
floorFloat :: Float -> Float
floorFloat :: Float -> Float
floorFloat = Float -> Float
c_floorf
roundDouble :: Double -> Double
roundDouble :: Double -> Double
roundDouble = Double -> Double
c_nearbyint
ceilDouble :: Double -> Double
ceilDouble :: Double -> Double
ceilDouble = Double -> Double
c_ceil
floorDouble :: Double -> Double
floorDouble :: Double -> Double
floorDouble = Double -> Double
c_floor
foreign import ccall "lgamma" c_lgamma :: Double -> Double
foreign import ccall "lgammaf" c_lgammaf :: Float -> Float
foreign import ccall "tgamma" c_tgamma :: Double -> Double
foreign import ccall "tgammaf" c_tgammaf :: Float -> Float
lgamma :: Double -> Double
lgamma :: Double -> Double
lgamma = Double -> Double
c_lgamma
lgammaf :: Float -> Float
lgammaf :: Float -> Float
lgammaf = Float -> Float
c_lgammaf
tgamma :: Double -> Double
tgamma :: Double -> Double
tgamma = Double -> Double
c_tgamma
tgammaf :: Float -> Float
tgammaf :: Float -> Float
tgammaf = Float -> Float
c_tgammaf
foreign import ccall "hypot" c_hypot :: Double -> Double -> Double
foreign import ccall "hypotf" c_hypotf :: Float -> Float -> Float
hypot :: Double -> Double -> Double
hypot :: Double -> Double -> Double
hypot = Double -> Double -> Double
c_hypot
hypotf :: Float -> Float -> Float
hypotf :: Float -> Float -> Float
hypotf = Float -> Float -> Float
c_hypotf
foreign import ccall "erf" c_erf :: Double -> Double
foreign import ccall "erff" c_erff :: Float -> Float
foreign import ccall "erfc" c_erfc :: Double -> Double
foreign import ccall "erfcf" c_erfcf :: Float -> Float
erf :: Double -> Double
erf :: Double -> Double
erf = Double -> Double
c_erf
erff :: Float -> Float
erff :: Float -> Float
erff = Float -> Float
c_erff
erfc :: Double -> Double
erfc :: Double -> Double
erfc = Double -> Double
c_erfc
erfcf :: Float -> Float
erfcf :: Float -> Float
erfcf = Float -> Float
c_erfcf
foreign import ccall "cbrt" c_cbrt :: Double -> Double
foreign import ccall "cbrtf" c_cbrtf :: Float -> Float
cbrt :: Double -> Double
cbrt :: Double -> Double
cbrt = Double -> Double
c_cbrt
cbrtf :: Float -> Float
cbrtf :: Float -> Float
cbrtf = Float -> Float
c_cbrtf
toPOSIX :: Native.FilePath -> Posix.FilePath
toPOSIX :: String -> String
toPOSIX = [String] -> String
Posix.joinPath ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
Native.splitDirectories
fromPOSIX :: Posix.FilePath -> Native.FilePath
fromPOSIX :: String -> String
fromPOSIX = [String] -> String
Native.joinPath ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
Posix.splitDirectories
trim :: String -> String
trim :: String -> String
trim = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace
pmapIO :: Maybe Int -> (a -> IO b) -> [a] -> IO [b]
pmapIO :: Maybe Int -> (a -> IO b) -> [a] -> IO [b]
pmapIO Maybe Int
concurrency a -> IO b
f [a]
elems = do
MVar [a]
tasks <- [a] -> IO (MVar [a])
forall a. a -> IO (MVar a)
newMVar [a]
elems
MVar (Either SomeException b)
results <- IO (MVar (Either SomeException b))
forall a. IO (MVar a)
newEmptyMVar
Int
num_threads <- IO Int -> (Int -> IO Int) -> Maybe Int -> IO Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO Int
getNumCapabilities Int -> IO Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Int
concurrency
Int -> IO ThreadId -> IO ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
num_threads (IO ThreadId -> IO ()) -> IO ThreadId -> IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ MVar [a] -> MVar (Either SomeException b) -> IO ()
forall a. Exception a => MVar [a] -> MVar (Either a b) -> IO ()
worker MVar [a]
tasks MVar (Either SomeException b)
results
Int -> IO b -> IO [b]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
elems) (IO b -> IO [b]) -> IO b -> IO [b]
forall a b. (a -> b) -> a -> b
$ MVar (Either SomeException b) -> IO b
forall b. MVar (Either SomeException b) -> IO b
getResult MVar (Either SomeException b)
results
where
worker :: MVar [a] -> MVar (Either a b) -> IO ()
worker MVar [a]
tasks MVar (Either a b)
results = do
Maybe a
task <- MVar [a] -> ([a] -> IO ([a], Maybe a)) -> IO (Maybe a)
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar MVar [a]
tasks [a] -> IO ([a], Maybe a)
forall (f :: * -> *) a. Applicative f => [a] -> f ([a], Maybe a)
getTask
case Maybe a
task of
Maybe a
Nothing -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just a
x -> do
Either a b
y <- (b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> IO b -> IO (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> IO b
f a
x) IO (Either a b) -> (a -> IO (Either a b)) -> IO (Either a b)
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` (Either a b -> IO (Either a b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either a b -> IO (Either a b))
-> (a -> Either a b) -> a -> IO (Either a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either a b
forall a b. a -> Either a b
Left)
MVar (Either a b) -> Either a b -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either a b)
results Either a b
y
MVar [a] -> MVar (Either a b) -> IO ()
worker MVar [a]
tasks MVar (Either a b)
results
getTask :: [a] -> f ([a], Maybe a)
getTask [] = ([a], Maybe a) -> f ([a], Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], Maybe a
forall a. Maybe a
Nothing)
getTask (a
task : [a]
tasks) = ([a], Maybe a) -> f ([a], Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([a]
tasks, a -> Maybe a
forall a. a -> Maybe a
Just a
task)
getResult :: MVar (Either SomeException b) -> IO b
getResult MVar (Either SomeException b)
results = do
Either SomeException b
res <- MVar (Either SomeException b) -> IO (Either SomeException b)
forall a. MVar a -> IO a
takeMVar MVar (Either SomeException b)
results
case Either SomeException b
res of
Left SomeException
err -> SomeException -> IO b
forall a e. Exception e => e -> a
throw (SomeException
err :: SomeException)
Right b
v -> b -> IO b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
v
interactWithFileSafely :: IO a -> IO (Maybe (Either String a))
interactWithFileSafely :: IO a -> IO (Maybe (Either String a))
interactWithFileSafely IO a
m =
(Either String a -> Maybe (Either String a)
forall a. a -> Maybe a
Just (Either String a -> Maybe (Either String a))
-> (a -> Either String a) -> a -> Maybe (Either String a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either String a
forall a b. b -> Either a b
Right (a -> Maybe (Either String a))
-> IO a -> IO (Maybe (Either String a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO a
m) IO (Maybe (Either String a))
-> (IOException -> IO (Maybe (Either String a)))
-> IO (Maybe (Either String a))
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` IOException -> IO (Maybe (Either String a))
forall (f :: * -> *) b.
Applicative f =>
IOException -> f (Maybe (Either String b))
couldNotRead
where
couldNotRead :: IOException -> f (Maybe (Either String b))
couldNotRead IOException
e
| IOException -> Bool
isDoesNotExistError IOException
e =
Maybe (Either String b) -> f (Maybe (Either String b))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Either String b)
forall a. Maybe a
Nothing
| Bool
otherwise =
Maybe (Either String b) -> f (Maybe (Either String b))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (Either String b) -> f (Maybe (Either String b)))
-> Maybe (Either String b) -> f (Maybe (Either String b))
forall a b. (a -> b) -> a -> b
$ Either String b -> Maybe (Either String b)
forall a. a -> Maybe a
Just (Either String b -> Maybe (Either String b))
-> Either String b -> Maybe (Either String b)
forall a b. (a -> b) -> a -> b
$ String -> Either String b
forall a b. a -> Either a b
Left (String -> Either String b) -> String -> Either String b
forall a b. (a -> b) -> a -> b
$ IOException -> String
forall a. Show a => a -> String
show IOException
e
convFloat :: (RealFloat from, RealFloat to) => from -> to
convFloat :: from -> to
convFloat from
v
| from -> Bool
forall a. RealFloat a => a -> Bool
isInfinite from
v, from
v from -> from -> Bool
forall a. Ord a => a -> a -> Bool
> from
0 = to
1 to -> to -> to
forall a. Fractional a => a -> a -> a
/ to
0
| from -> Bool
forall a. RealFloat a => a -> Bool
isInfinite from
v, from
v from -> from -> Bool
forall a. Ord a => a -> a -> Bool
< from
0 = -to
1 to -> to -> to
forall a. Fractional a => a -> a -> a
/ to
0
| from -> Bool
forall a. RealFloat a => a -> Bool
isNaN from
v = to
0 to -> to -> to
forall a. Fractional a => a -> a -> a
/ to
0
| Bool
otherwise = Rational -> to
forall a. Fractional a => Rational -> a
fromRational (Rational -> to) -> Rational -> to
forall a b. (a -> b) -> a -> b
$ from -> Rational
forall a. Real a => a -> Rational
toRational from
v
type UserString = String
type EncodedString = String
zEncodeString :: UserString -> EncodedString
zEncodeString :: String -> String
zEncodeString String
"" = String
""
zEncodeString (Char
c : String
cs) = Char -> String
encodeDigitChar Char
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
encodeChar String
cs
unencodedChar :: Char -> Bool
unencodedChar :: Char -> Bool
unencodedChar Char
'Z' = Bool
False
unencodedChar Char
'z' = Bool
False
unencodedChar Char
'_' = Bool
True
unencodedChar Char
c =
Char -> Bool
isAsciiLower Char
c
Bool -> Bool -> Bool
|| Char -> Bool
isAsciiUpper Char
c
Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c
encodeDigitChar :: Char -> EncodedString
encodeDigitChar :: Char -> String
encodeDigitChar Char
c
| Char -> Bool
isDigit Char
c = Char -> String
encodeAsUnicodeCharar Char
c
| Bool
otherwise = Char -> String
encodeChar Char
c
encodeChar :: Char -> EncodedString
encodeChar :: Char -> String
encodeChar Char
c | Char -> Bool
unencodedChar Char
c = [Char
c]
encodeChar Char
'(' = String
"ZL"
encodeChar Char
')' = String
"ZR"
encodeChar Char
'[' = String
"ZM"
encodeChar Char
']' = String
"ZN"
encodeChar Char
':' = String
"ZC"
encodeChar Char
'Z' = String
"ZZ"
encodeChar Char
'z' = String
"zz"
encodeChar Char
'&' = String
"za"
encodeChar Char
'|' = String
"zb"
encodeChar Char
'^' = String
"zc"
encodeChar Char
'$' = String
"zd"
encodeChar Char
'=' = String
"ze"
encodeChar Char
'>' = String
"zg"
encodeChar Char
'#' = String
"zh"
encodeChar Char
'.' = String
"zi"
encodeChar Char
'<' = String
"zl"
encodeChar Char
'-' = String
"zm"
encodeChar Char
'!' = String
"zn"
encodeChar Char
'+' = String
"zp"
encodeChar Char
'\'' = String
"zq"
encodeChar Char
'\\' = String
"zr"
encodeChar Char
'/' = String
"zs"
encodeChar Char
'*' = String
"zt"
encodeChar Char
'_' = String
"zu"
encodeChar Char
'%' = String
"zv"
encodeChar Char
c = Char -> String
encodeAsUnicodeCharar Char
c
encodeAsUnicodeCharar :: Char -> EncodedString
encodeAsUnicodeCharar :: Char -> String
encodeAsUnicodeCharar Char
c =
Char
'z'
Char -> String -> String
forall a. a -> [a] -> [a]
: if Char -> Bool
isDigit (String -> Char
forall a. [a] -> a
head String
hex_str)
then String
hex_str
else Char
'0' Char -> String -> String
forall a. a -> [a] -> [a]
: String
hex_str
where
hex_str :: String
hex_str = Int -> String -> String
forall a. (Integral a, Show a) => a -> String -> String
showHex (Char -> Int
ord Char
c) String
"U"
atMostChars :: Int -> String -> String
atMostChars :: Int -> String -> String
atMostChars Int
n String
s
| String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
n = Int -> String -> String
forall a. Int -> [a] -> [a]
take (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"..."
| Bool
otherwise = String
s
invertMap :: (Ord v, Ord k) => M.Map k v -> M.Map v (S.Set k)
invertMap :: Map k v -> Map v (Set k)
invertMap Map k v
m =
Map k v -> [(k, v)]
forall k a. Map k a -> [(k, a)]
M.toList Map k v
m
[(k, v)] -> ([(k, v)] -> [(v, Set k)]) -> [(v, Set k)]
forall a b. a -> (a -> b) -> b
& ((k, v) -> (v, Set k)) -> [(k, v)] -> [(v, Set k)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Set k, v) -> (v, Set k)
forall a b. (a, b) -> (b, a)
swap ((Set k, v) -> (v, Set k))
-> ((k, v) -> (Set k, v)) -> (k, v) -> (v, Set k)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (k -> Set k) -> (k, v) -> (Set k, v)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first k -> Set k
forall a. a -> Set a
S.singleton)
[(v, Set k)] -> ([(v, Set k)] -> Map v (Set k)) -> Map v (Set k)
forall a b. a -> (a -> b) -> b
& ((v, Set k) -> Map v (Set k) -> Map v (Set k))
-> Map v (Set k) -> [(v, Set k)] -> Map v (Set k)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((v -> Set k -> Map v (Set k) -> Map v (Set k))
-> (v, Set k) -> Map v (Set k) -> Map v (Set k)
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((v -> Set k -> Map v (Set k) -> Map v (Set k))
-> (v, Set k) -> Map v (Set k) -> Map v (Set k))
-> (v -> Set k -> Map v (Set k) -> Map v (Set k))
-> (v, Set k)
-> Map v (Set k)
-> Map v (Set k)
forall a b. (a -> b) -> a -> b
$ (Set k -> Set k -> Set k)
-> v -> Set k -> Map v (Set k) -> Map v (Set k)
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith Set k -> Set k -> Set k
forall a. Semigroup a => a -> a -> a
(<>)) Map v (Set k)
forall a. Monoid a => a
mempty
traverseFold :: (Monoid m, Traversable t, Applicative f) => (a -> f m) -> t a -> f m
traverseFold :: (a -> f m) -> t a -> f m
traverseFold a -> f m
f = (t m -> m) -> f (t m) -> f m
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap t m -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (f (t m) -> f m) -> (t a -> f (t m)) -> t a -> f m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f m) -> t a -> f (t m)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f m
f
fixPoint :: Eq a => (a -> a) -> a -> a
fixPoint :: (a -> a) -> a -> a
fixPoint a -> a
f a
x =
let x' :: a
x' = a -> a
f a
x
in if a
x' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x then a
x else (a -> a) -> a -> a
forall a. Eq a => (a -> a) -> a -> a
fixPoint a -> a
f a
x'