classy-prelude 0.7.0 → 0.8.0
raw patch · 5 files changed
+44/−425 lines, 5 filesdep +chunked-datadep +enclosed-exceptionsdep −asyncdep −deepseqdep −monad-control
Dependencies added: chunked-data, enclosed-exceptions
Dependencies removed: async, deepseq, monad-control
Files
- ClassyPrelude.hs +41/−108
- ClassyPrelude/Classes.hs +0/−255
- Data/Sequences/Lazy.hs +0/−27
- Data/Textual/Encoding.hs +0/−28
- classy-prelude.cabal +3/−7
ClassyPrelude.hs view
@@ -36,6 +36,8 @@ , module Data.Sequences.Lazy , module Data.Textual.Encoding , module Data.Containers+ , module Data.Builder+ , module Data.MinLen -- * I\/O , Handle , stdin@@ -98,16 +100,10 @@ , fpFromString , fpToText , fpFromText+ , fpToTextWarn+ , fpToTextEx -- ** Exceptions- , catchAny- , handleAny- , tryAny- , catchAnyDeep- , handleAnyDeep- , tryAnyDeep- , catchIO- , handleIO- , tryIO+ , module Control.Exception.Enclosed -- ** Force types -- | Helper functions for situations where type inferer gets confused. , asByteString@@ -122,30 +118,29 @@ , asSet , asVector , asUVector- , asIOException- , asSomeException ) where import qualified Prelude import Control.Exception (assert)+import Control.Exception.Enclosed import Control.Monad (when, unless, void, liftM, ap, forever, join, sequence, sequence_, replicateM_)-import Control.Monad.Trans.Control (MonadBaseControl, liftBaseWith, restoreM)-import Control.Concurrent.Async (withAsync, waitCatch) import Control.Concurrent.MVar.Lifted import Data.IORef.Lifted import qualified Data.Monoid as Monoid import qualified Data.Traversable as Traversable import Data.Traversable (Traversable) import Data.Foldable (Foldable)-import Control.DeepSeq (NFData, ($!!))+import Data.IOData (IOData (..)) import Data.Vector.Instances () import CorePrelude hiding (print, undefined, (<>))-import ClassyPrelude.Classes+import Data.ChunkedZip import qualified Data.Char as Char import Data.Sequences import Data.MonoTraversable import Data.Containers+import Data.Builder+import Data.MinLen import qualified Filesystem.Path.CurrentOS as F import System.IO (Handle, stdin, stdout, stderr, hClose) @@ -159,6 +154,7 @@ , fromGregorian , formatTime , parseTime+ , getCurrentTime ) import System.Locale (defaultTimeLocale) @@ -336,101 +332,8 @@ undefined = error "ClassyPrelude.undefined" {-# DEPRECATED undefined "It is highly recommended that you either avoid partial functions or provide meaningful error messages" #-} --- | A version of 'catch' which is specialized for any exception. This--- simplifies usage as no explicit type signatures are necessary.------ Note that since version 0.5.9, this function now has proper support for--- asynchronous exceptions, by only catching exceptions generated by the--- internal action.------ Since 0.5.6-catchAny :: MonadBaseControl IO m => m a -> (SomeException -> m a) -> m a-catchAny action onE = tryAny action >>= either onE return---- | A version of 'handle' which is specialized for any exception. This--- simplifies usage as no explicit type signatures are necessary.------ Note that since version 0.5.9, this function now has proper support for--- asynchronous exceptions, by only catching exceptions generated by the--- internal action.------ Since 0.5.6-handleAny :: MonadBaseControl IO m => (SomeException -> m a) -> m a -> m a-handleAny = flip catchAny---- | A version of 'try' which is specialized for any exception.--- This simplifies usage as no explicit type signatures are necessary.------ Note that since version 0.5.9, this function now has proper support for--- asynchronous exceptions, by only catching exceptions generated by the--- internal action.------ Since 0.5.6-tryAny :: MonadBaseControl IO m => m a -> m (Either SomeException a)-tryAny m =- liftBaseWith (\runInIO -> withAsync (runInIO m) waitCatch) >>=- either (return . Left) (liftM Right . restoreM)---- | An extension to @catchAny@ which ensures that the return value is fully--- evaluated. See @tryAnyDeep@.------ Since 0.5.9-catchAnyDeep :: (NFData a, MonadBaseControl IO m) => m a -> (SomeException -> m a) -> m a-catchAnyDeep action onE = tryAnyDeep action >>= either onE return---- | @flip catchAnyDeep@------ Since 0.5.6-handleAnyDeep :: (NFData a, MonadBaseControl IO m) => (SomeException -> m a) -> m a -> m a-handleAnyDeep = flip catchAnyDeep---- | An extension to @tryAny@ which ensures that the return value is fully--- evaluated. In other words, if you get a @Right@ response here, you can be--- confident that using it will not result in another exception.------ Since 0.5.9-tryAnyDeep :: (NFData a, MonadBaseControl IO m)- => m a- -> m (Either SomeException a)-tryAnyDeep m = tryAny $ do- x <- m- return $!! x---- | A version of 'catch' which is specialized for IO exceptions. This--- simplifies usage as no explicit type signatures are necessary.------ Since 0.5.6-catchIO :: MonadBaseControl IO m => m a -> (IOException -> m a) -> m a-catchIO = catch---- | A version of 'handle' which is specialized for IO exceptions. This--- simplifies usage as no explicit type signatures are necessary.------ Since 0.5.6-handleIO :: MonadBaseControl IO m => (IOException -> m a) -> m a -> m a-handleIO = handle---- | A version of 'try' which is specialized for IO exceptions.--- This simplifies usage as no explicit type signatures are necessary.------ Since 0.5.6-tryIO :: MonadBaseControl IO m => m a -> m (Either IOException a)-tryIO = try- -- | ----- Since 0.5.6-asSomeException :: SomeException -> SomeException-asSomeException = id---- |------ Since 0.5.6-asIOException :: IOException -> IOException-asIOException = id---- |--- -- Since 0.5.9 traceId :: String -> String traceId a = trace a a@@ -459,6 +362,36 @@ fpFromString :: String -> FilePath fpFromString = F.decodeString +-- | Translates a FilePath to a Text+-- Warns if there are non-unicode+-- sequences in the file name+fpToTextWarn :: MonadIO m => FilePath -> m Text+fpToTextWarn fp = case F.toText fp of+ Right ok -> return ok+ Left bad -> do+ putStrLn $ pack $ "non-unicode filepath: " ++ F.encodeString fp+ return bad++-- | Translates a FilePath to a Text+-- Throws an exception if there are non-unicode+-- sequences in the file name+--+-- Use this to assert that you know+-- a filename will translate properly into a Text+-- If you created the filename, this should be the case.+fpToTextEx :: FilePath -> Text+fpToTextEx fp = either (const $ error errorMsg) id $ F.toText fp+ where+ errorMsg = "fpToTextEx: non-unicode filepath: " ++ F.encodeString fp++-- | Translates a FilePath to a Text+-- This translation is not correct for a (unix) filename+-- which can contain arbitrary (non-unicode) bytes: those bytes will be discarded+--+-- This means you cannot translate the Text back to the original file name.+--+-- If you control or otherwise understand the filenames+-- and believe them to be unicode valid consider using 'fpToTextEx' or 'fpToTextWarn' fpToText :: FilePath -> Text fpToText = either id id . F.toText
− ClassyPrelude/Classes.hs
@@ -1,255 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE UndecidableInstances #-}-module ClassyPrelude.Classes where--import CorePrelude-import qualified Prelude-import qualified Data.List as List-import qualified Data.List.NonEmpty as NonEmpty-import Data.List.NonEmpty (NonEmpty)-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Char8 as ByteString8-import qualified Data.ByteString.Lazy as LByteString-import qualified Data.Text as Text-import qualified Data.Text.IO as Text-import qualified Data.Text.Lazy.IO as LText-import qualified Filesystem.Path.CurrentOS as FilePath-import qualified Data.Vector as Vector--- import qualified Data.Vector.Unboxed as UVector-import qualified Data.Sequence as Seq-import Data.Sequences (IsSequence)-import Data.Sequences.Lazy (fromStrict)-import Control.Monad (liftM)-import System.IO (Handle)-import qualified System.IO-import Data.ByteString.Lazy.Internal (defaultChunkSize)-import Control.Monad.Trans.Identity-import Control.Monad.Trans.Reader-import qualified Data.IntMap as IntMap-import Data.Tree-import Data.Functor.Compose-import Data.Foldable (toList)--class IsSequence a => IOData a where- readFile :: MonadIO m => FilePath -> m a- writeFile :: MonadIO m => FilePath -> a -> m ()- getLine :: MonadIO m => m a- hGetContents :: MonadIO m => Handle -> m a- hGetLine :: MonadIO m => Handle -> m a- hPut :: MonadIO m => Handle -> a -> m ()- hPutStrLn :: MonadIO m => Handle -> a -> m ()- hGetChunk :: MonadIO m => Handle -> m a-instance IOData ByteString where- readFile = liftIO . ByteString.readFile . FilePath.encodeString- writeFile fp = liftIO . ByteString.writeFile (FilePath.encodeString fp)- getLine = liftIO ByteString.getLine- hGetContents = liftIO . ByteString.hGetContents- hGetLine = liftIO . ByteString.hGetLine- hPut h = liftIO . ByteString.hPut h- hPutStrLn h = liftIO . ByteString8.hPutStrLn h- hGetChunk = liftIO . flip ByteString.hGetSome defaultChunkSize-instance IOData LByteString where- readFile = liftIO . LByteString.readFile . FilePath.encodeString- writeFile fp = liftIO . LByteString.writeFile (FilePath.encodeString fp)- getLine = liftM fromStrict (liftIO ByteString.getLine)- hGetContents = liftIO . LByteString.hGetContents- hGetLine = liftM fromStrict . liftIO . ByteString.hGetLine- hPut h = liftIO . LByteString.hPut h- hPutStrLn h lbs = liftIO $ do- LByteString.hPutStr h lbs- ByteString8.hPutStrLn h ByteString.empty- hGetChunk = liftM fromStrict . hGetChunk-instance IOData Text where- readFile = liftIO . Text.readFile . FilePath.encodeString- writeFile fp = liftIO . Text.writeFile (FilePath.encodeString fp)- getLine = liftIO Text.getLine- hGetContents = liftIO . Text.hGetContents- hGetLine = liftIO . Text.hGetLine- hPut h = liftIO . Text.hPutStr h- hPutStrLn h = liftIO . Text.hPutStrLn h-#if MIN_VERSION_text(0, 11, 3)- hGetChunk = liftIO . Text.hGetChunk-#else- -- Dangerously inefficient!- hGetChunk = liftIO . liftM Text.singleton . System.IO.hGetChar-#endif-instance IOData LText where- readFile = liftIO . LText.readFile . FilePath.encodeString- writeFile fp = liftIO . LText.writeFile (FilePath.encodeString fp)- getLine = liftIO LText.getLine- hGetContents = liftIO . LText.hGetContents- hGetLine = liftIO . LText.hGetLine- hPut h = liftIO . LText.hPutStr h- hPutStrLn h = liftIO . LText.hPutStrLn h- hGetChunk = liftM fromStrict . hGetChunk-instance (Char ~ c) => IOData [c] where- readFile = liftIO . Prelude.readFile . FilePath.encodeString- writeFile fp = liftIO . Prelude.writeFile (FilePath.encodeString fp)- getLine = liftIO Prelude.getLine- hGetContents = liftIO . System.IO.hGetContents- hGetLine = liftIO . System.IO.hGetLine- hPut h = liftIO . System.IO.hPutStr h- hPutStrLn h = liftIO . System.IO.hPutStrLn h- hGetChunk = liftM Text.unpack . hGetChunk---class Functor f => Zip f where- zipWith :: (a -> b -> c) -> f a -> f b -> f c-- zip :: f a -> f b -> f (a, b)- zip = zipWith (,)-- zap :: f (a -> b) -> f a -> f b- zap = zipWith id-- unzip :: f (a, b) -> (f a, f b)- unzip = fmap fst &&& fmap snd--instance Zip [] where- zip = List.zip- zipWith = List.zipWith- unzip = List.unzip-instance Zip NonEmpty where- zipWith = NonEmpty.zipWith- zip = NonEmpty.zip- unzip = NonEmpty.unzip-instance Zip Seq where- zip = Seq.zip- zipWith = Seq.zipWith- unzip = (Seq.fromList *** Seq.fromList) . List.unzip . toList-instance Zip Tree where- zipWith f (Node a as) (Node b bs) = Node (f a b) (zipWith (zipWith f) as bs)-instance Zip Vector where- zip = Vector.zip- unzip = Vector.unzip- zipWith = Vector.zipWith- {--instance Zip UVector where- zip = UVector.zip- unzip = UVector.unzip- zipWith = UVector.zipWith- -}--instance Zip m => Zip (IdentityT m) where- zipWith f (IdentityT m) (IdentityT n) = IdentityT (zipWith f m n)-instance Zip ((->)a) where- zipWith f g h a = f (g a) (h a)-instance Zip m => Zip (ReaderT e m) where- zipWith f (ReaderT m) (ReaderT n) = ReaderT $ \a ->- zipWith f (m a) (n a)-instance Zip IntMap.IntMap where- zipWith = IntMap.intersectionWith-instance (Zip f, Zip g) => Zip (Compose f g) where- zipWith f (Compose a) (Compose b) = Compose $ zipWith (zipWith f) a b--class Functor f => Zip3 f where- zipWith3 :: (a -> b -> c -> d) -> f a -> f b -> f c -> f d-- zip3 :: f a -> f b -> f c -> f (a, b, c)- zip3 = zipWith3 (\x y z -> (x,y,z))-- zap3 :: f (a -> b -> c) -> f a -> f b -> f c- zap3 = zipWith3 id-- unzip3 :: f (a, b, c) -> (f a, f b, f c)- -- unzip3 = fmap (\(x,_,_)->x) &&& fmap (\(_,x,_)->x) &&& fmap (\(_,_,x)->x)--instance Zip3 [] where- zip3 = List.zip3- unzip3 = List.unzip3- zipWith3 = List.zipWith3-instance Zip3 Vector where- zip3 = Vector.zip3- unzip3 = Vector.unzip3- zipWith3 = Vector.zipWith3-instance Zip3 Seq where- zip3 = Seq.zip3- unzip3 = (\(a, b, c) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c)) . List.unzip3 . toList- zipWith3 = Seq.zipWith3--class Functor f => Zip4 f where- zipWith4 :: (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e-- zip4 :: f a -> f b -> f c -> f d -> f (a, b, c, d)- zip4 = zipWith4 (\w x y z -> (w, x,y,z))-- zap4 :: f (a -> b -> c -> d) -> f a -> f b -> f c -> f d- zap4 = zipWith4 id-- unzip4 :: f (a, b, c, d) -> (f a, f b, f c, f d)--instance Zip4 [] where- zip4 = List.zip4- unzip4 = List.unzip4- zipWith4 = List.zipWith4-instance Zip4 Vector where- zip4 = Vector.zip4- unzip4 = Vector.unzip4- zipWith4 = Vector.zipWith4-instance Zip4 Seq where- zip4 = Seq.zip4- unzip4 = (\(a, b, c, d) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c, Seq.fromList d)) . List.unzip4 . toList- zipWith4 = Seq.zipWith4--class Functor f => Zip5 f where- zipWith5 :: (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g-- zip5 :: f a -> f b -> f c -> f d -> f e -> f (a, b, c, d, e)- zip5 = zipWith5 (\v w x y z -> (v,w,x,y,z))-- zap5 :: f (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e- zap5 = zipWith5 id-- unzip5 :: f (a, b, c, d, e) -> (f a, f b, f c, f d, f e)--instance Zip5 [] where- zip5 = List.zip5- unzip5 = List.unzip5- zipWith5 = List.zipWith5-instance Zip5 Vector where- zip5 = Vector.zip5- unzip5 = Vector.unzip5- zipWith5 = Vector.zipWith5--class Functor f => Zip6 f where- zipWith6 :: (a -> b -> c -> d -> e -> g -> h) -> f a -> f b -> f c -> f d -> f e -> f g -> f h-- zip6 :: f a -> f b -> f c -> f d -> f e -> f g -> f (a, b, c, d, e, g)- zip6 = zipWith6 (\u v w x y z -> (u, v,w,x,y,z))-- zap6 :: f (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g- zap6 = zipWith6 id-- unzip6 :: f (a, b, c, d, e, g) -> (f a, f b, f c, f d, f e, f g)--instance Zip6 [] where- zip6 = List.zip6- unzip6 = List.unzip6- zipWith6 = List.zipWith6-instance Zip6 Vector where- zip6 = Vector.zip6- unzip6 = Vector.unzip6- zipWith6 = Vector.zipWith6--class Functor f => Zip7 f where- zipWith7 :: (a -> b -> c -> d -> e -> g -> h -> i) -> f a -> f b -> f c -> f d -> f e -> f g -> f h -> f i-- zip7 :: f a -> f b -> f c -> f d -> f e -> f g -> f h -> f (a, b, c, d, e, g, h)- zip7 = zipWith7 (\t u v w x y z -> (t,u,v,w,x,y,z))-- zap7 :: f (a -> b -> c -> d -> e -> g -> h) -> f a -> f b -> f c -> f d -> f e -> f g -> f h- zap7 = zipWith7 id-- unzip7 :: f (a, b, c, d, e, g, h) -> (f a, f b, f c, f d, f e, f g, f h)- -- unzip3 = fmap (\(x,_,_)->x) &&& fmap (\(_,x,_)->x) &&& fmap (\(_,_,x)->x)--instance Zip7 [] where- zip7 = List.zip7- unzip7 = List.unzip7- zipWith7 = List.zipWith7
− Data/Sequences/Lazy.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-module Data.Sequences.Lazy where--import qualified Data.ByteString as S-import qualified Data.ByteString.Lazy as L-import Data.Sequences-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL--class (IsSequence l, IsSequence s) => LazySequence l s | l -> s, s -> l where- toChunks :: l -> [s]- fromChunks :: [s] -> l- toStrict :: l -> s- fromStrict :: s -> l--instance LazySequence L.ByteString S.ByteString where- toChunks = L.toChunks- fromChunks = L.fromChunks- toStrict = S.concat . L.toChunks- fromStrict = L.fromChunks . return--instance LazySequence TL.Text T.Text where- toChunks = TL.toChunks- fromChunks = TL.fromChunks- toStrict = TL.toStrict- fromStrict = TL.fromStrict
− Data/Textual/Encoding.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-module Data.Textual.Encoding where--import qualified Data.ByteString as S-import qualified Data.ByteString.Lazy as L-import Data.Sequences-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import Data.Text.Encoding.Error (lenientDecode)-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Encoding as TL-import Data.Word (Word8)--class (Textual t, IsSequence b) => Utf8 t b | t -> b, b -> t where- encodeUtf8 :: t -> b- decodeUtf8 :: b -> t-instance (c ~ Char, w ~ Word8) => Utf8 [c] [w] where- encodeUtf8 = L.unpack . TL.encodeUtf8 . TL.pack- decodeUtf8 = TL.unpack . TL.decodeUtf8With lenientDecode . L.pack-instance Utf8 T.Text S.ByteString where- encodeUtf8 = T.encodeUtf8- decodeUtf8 = T.decodeUtf8With lenientDecode-instance Utf8 TL.Text L.ByteString where- encodeUtf8 = TL.encodeUtf8- decodeUtf8 = TL.decodeUtf8With lenientDecode
classy-prelude.cabal view
@@ -1,5 +1,5 @@ name: classy-prelude-version: 0.7.0+version: 0.8.0 synopsis: A typeclass-based Prelude. description: Focuses on using common typeclasses when possible, and creating new ones to avoid name clashing. Exposes many recommended datastructures (Map, ByteString, etc) directly without requiring long import lists and qualified modules. homepage: https://github.com/snoyberg/classy-prelude@@ -13,9 +13,6 @@ library exposed-modules: ClassyPrelude- ClassyPrelude.Classes- Data.Sequences.Lazy- Data.Textual.Encoding build-depends: base >= 4 && < 5 , basic-prelude >= 0.3.6 && < 0.4 , system-filepath >= 0.4 && < 0.5@@ -27,14 +24,13 @@ , unordered-containers , hashable , lifted-base >= 0.2- , monad-control- , async >= 2.0- , deepseq , mono-traversable >= 0.2 , semigroups , vector-instances , old-locale , time+ , chunked-data+ , enclosed-exceptions ghc-options: -Wall -fno-warn-orphans test-suite test