classy-prelude 0.3.1 → 0.4.0
raw patch · 10 files changed
+173/−6 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- ClassyPrelude.Classes: instance CanFilterFunc ci co i => CanFilter (ci -> co) i
+ ClassyPrelude: decodeUtf8 :: CanDecodeUtf8 f => f
+ ClassyPrelude: encodeUtf8 :: CanEncodeUtf8 f => f
+ ClassyPrelude: forM :: CanMapMFunc ci mco m i o => ci -> (i -> m o) -> mco
+ ClassyPrelude: forM_ :: (Monad m, CanMapM_Func ci i) => ci -> (i -> m o) -> m ()
+ ClassyPrelude: replicateM :: (CanReplicateM c i len, Monad m) => len -> m i -> m c
+ ClassyPrelude.Classes: class CanDecodeUtf8 f
+ ClassyPrelude.Classes: class CanDecodeUtf8Func ci co | co -> ci, ci -> co
+ ClassyPrelude.Classes: class CanEncodeUtf8 f
+ ClassyPrelude.Classes: class CanEncodeUtf8Func ci co | co -> ci, ci -> co
+ ClassyPrelude.Classes: class CanFilterM f m i
+ ClassyPrelude.Classes: class CanFilterMFunc c i | c -> i
+ ClassyPrelude.Classes: class CanLines f
+ ClassyPrelude.Classes: class CanLinesFunc t
+ ClassyPrelude.Classes: class CanReplicateM c i len | c -> i len
+ ClassyPrelude.Classes: class CanUnlines t
+ ClassyPrelude.Classes: decodeUtf8 :: CanDecodeUtf8 f => f
+ ClassyPrelude.Classes: decodeUtf8Func :: CanDecodeUtf8Func ci co => ci -> co
+ ClassyPrelude.Classes: encodeUtf8 :: CanEncodeUtf8 f => f
+ ClassyPrelude.Classes: encodeUtf8Func :: CanEncodeUtf8Func ci co => ci -> co
+ ClassyPrelude.Classes: filterM :: CanFilterM f m i => (i -> m Bool) -> f
+ ClassyPrelude.Classes: filterMFunc :: (CanFilterMFunc c i, Monad m) => (i -> m Bool) -> c -> m c
+ ClassyPrelude.Classes: instance (CanFilterFunc ci co i, ci ~ co) => CanFilter (ci -> co) i
+ ClassyPrelude.Classes: instance (CanFilterMFunc ci i, m ci ~ mco, Monad m) => CanFilterM (ci -> mco) m i
+ ClassyPrelude.Classes: instance (CanLinesFunc t, out ~ [t]) => CanLines (t -> out)
+ ClassyPrelude.Classes: instance CanDecodeUtf8Func ci co => CanDecodeUtf8 (ci -> co)
+ ClassyPrelude.Classes: instance CanEncodeUtf8Func ci co => CanEncodeUtf8 (ci -> co)
+ ClassyPrelude.Classes: linesFunc :: CanLinesFunc t => t -> [t]
+ ClassyPrelude.Classes: replicateM :: (CanReplicateM c i len, Monad m) => len -> m i -> m c
- ClassyPrelude: lines :: CanWords t => t -> [t]
+ ClassyPrelude: lines :: CanLines f => f
- ClassyPrelude: unlines :: CanWords t => [t] -> t
+ ClassyPrelude: unlines :: CanUnlines t => [t] -> t
- ClassyPrelude.Classes: lines :: CanWords t => t -> [t]
+ ClassyPrelude.Classes: lines :: CanLines f => f
- ClassyPrelude.Classes: unlines :: CanWords t => [t] -> t
+ ClassyPrelude.Classes: unlines :: CanUnlines t => [t] -> t
Files
- ClassyPrelude.hs +14/−0
- ClassyPrelude/ByteString.hs +6/−0
- ClassyPrelude/Classes.hs +37/−2
- ClassyPrelude/LByteString.hs +6/−0
- ClassyPrelude/LText.hs +13/−1
- ClassyPrelude/List.hs +11/−1
- ClassyPrelude/Text.hs +13/−1
- ClassyPrelude/Vector.hs +5/−0
- classy-prelude.cabal +1/−1
- test/main.hs +67/−0
ClassyPrelude.hs view
@@ -12,6 +12,8 @@ , empty , append , (++)+ -- ** Monad+ , module Control.Monad -- * Non-standard -- ** List-like classes , map@@ -27,6 +29,9 @@ , toList , mapM , mapM_+ , forM+ , forM_+ , replicateM , stripPrefix , isPrefixOf , stripSuffix@@ -48,6 +53,8 @@ , reverse , readMay , replicate+ , encodeUtf8+ , decodeUtf8 -- ** Map-like , lookup , insert@@ -77,6 +84,7 @@ import qualified Prelude import qualified Data.Maybe+import Control.Monad (when, unless, void, liftM, ap, forever) import CorePrelude import ClassyPrelude.Classes@@ -166,3 +174,9 @@ asVector :: Vector a -> Vector a asVector = id++forM :: CanMapMFunc ci mco m i o => ci -> (i -> m o) -> mco+forM = flip mapM++forM_ :: (Monad m, CanMapM_Func ci i) => ci -> (i -> m o) -> m ()+forM_ = flip mapM_
ClassyPrelude/ByteString.hs view
@@ -53,3 +53,9 @@ instance CanReplicate ByteString Word8 Prelude.Int where replicate = S.replicate++instance CanStripSuffix ByteString where+ stripSuffix x y+ | x `S.isSuffixOf` y = Prelude.Just (S.take (S.length y Prelude.- S.length x) y)+ | Prelude.otherwise = Prelude.Nothing+ isSuffixOf = S.isSuffixOf
ClassyPrelude/Classes.hs view
@@ -28,9 +28,16 @@ filter :: (i -> Prelude.Bool) -> f class CanFilterFunc ci co i | ci -> i co where filterFunc :: (i -> Prelude.Bool) -> ci -> co-instance (CanFilterFunc ci co i) => CanFilter (ci -> co) i where+instance (CanFilterFunc ci co i, ci ~ co) => CanFilter (ci -> co) i where filter = filterFunc +class CanFilterM f m i where+ filterM :: (i -> m Prelude.Bool) -> f+class CanFilterMFunc c i | c -> i where+ filterMFunc :: Monad m => (i -> m Prelude.Bool) -> c -> m c+instance (CanFilterMFunc ci i, m ci ~ mco, Monad m) => CanFilterM (ci -> mco) m i where+ filterM = filterMFunc+ class CanLength c len | c -> len where length :: c -> len @@ -58,6 +65,9 @@ instance (Monad m, CanMapM_Func ci i, r ~ m ()) => CanMapM_ (ci -> r) m i where mapM_ = mapM_Func +class CanReplicateM c i len | c -> i len where+ replicateM :: Monad m => len -> m i -> m c+ class CanLookup c k v | c -> k v where lookup :: k -> c -> Prelude.Maybe v @@ -118,7 +128,15 @@ class CanWords t where words :: t -> [t] unwords :: [t] -> t- lines :: t -> [t]++class CanLines f where+ lines :: f+class CanLinesFunc t where+ linesFunc :: t -> [t]+instance (CanLinesFunc t, out ~ [t]) => CanLines (t -> out) where+ lines = linesFunc++class CanUnlines t where unlines :: [t] -> t class CanSplit c i | c -> i where@@ -140,3 +158,20 @@ class CanToChunks c i | c -> i, i -> c where toChunks :: c -> [i] fromChunks :: [i] -> c++class CanEncodeUtf8 f where+ encodeUtf8 :: f+class CanEncodeUtf8Func ci co | co -> ci, ci -> co where+ encodeUtf8Func :: ci -> co+instance CanEncodeUtf8Func ci co => CanEncodeUtf8 (ci -> co) where+ encodeUtf8 = encodeUtf8Func++class CanDecodeUtf8 f where+ decodeUtf8 :: f+-- | Note: implementations should ensure that @decodeUtf8Func@ is a total+-- function. As such, the standard @decodeUtf8@ provided by the text package+-- should not be used, but instead @decodeUtf8With lenientDecode@.+class CanDecodeUtf8Func ci co | co -> ci, ci -> co where+ decodeUtf8Func :: ci -> co+instance CanDecodeUtf8Func ci co => CanDecodeUtf8 (ci -> co) where+ decodeUtf8 = decodeUtf8Func
ClassyPrelude/LByteString.hs view
@@ -60,3 +60,9 @@ instance CanToChunks LByteString Data.ByteString.ByteString where toChunks = L.toChunks fromChunks = L.fromChunks++instance CanStripSuffix LByteString where+ stripSuffix x y+ | x `L.isSuffixOf` y = Prelude.Just (L.take (L.length y Prelude.- L.length x) y)+ | Prelude.otherwise = Prelude.Nothing+ isSuffixOf = L.isSuffixOf
ClassyPrelude/LText.hs view
@@ -12,6 +12,9 @@ import qualified Data.Text.Lazy as TL import Data.Int (Int64) import qualified Data.Text+import qualified Data.Text.Lazy.Encoding+import qualified Data.Text.Encoding.Error+import Data.ByteString.Lazy (ByteString) type LText = TL.Text @@ -45,7 +48,11 @@ instance CanWords LText where words = TL.words unwords = TL.unwords- lines = TL.lines++instance CanLinesFunc LText where+ linesFunc = TL.lines++instance CanUnlines LText where unlines = TL.unlines instance CanSplit LText Char where@@ -73,3 +80,8 @@ instance CanToChunks LText Data.Text.Text where toChunks = TL.toChunks fromChunks = TL.fromChunks++instance CanEncodeUtf8Func LText ByteString where+ encodeUtf8Func = Data.Text.Lazy.Encoding.encodeUtf8+instance CanDecodeUtf8Func ByteString LText where+ decodeUtf8Func = Data.Text.Lazy.Encoding.decodeUtf8With Data.Text.Encoding.Error.lenientDecode
ClassyPrelude/List.hs view
@@ -8,6 +8,7 @@ import Prelude ((.)) import ClassyPrelude.Classes import qualified Data.List+import qualified Control.Monad instance CanMapFunc [a] [b] a b where mapFunc = Prelude.map@@ -15,6 +16,8 @@ concatMapFunc = Prelude.concatMap instance CanFilterFunc [a] [a] a where filterFunc = Prelude.filter+instance CanFilterMFunc [a] a where+ filterMFunc = Control.Monad.filterM instance CanLength [a] Prelude.Int where length = Prelude.length instance CanSingleton [a] a where@@ -55,7 +58,11 @@ instance (c ~ Prelude.Char) => CanWords [c] where words = Prelude.words unwords = Prelude.unwords- lines = Prelude.lines++instance (c ~ Prelude.Char) => CanLinesFunc [c] where+ linesFunc = Prelude.lines++instance (c ~ Prelude.Char) => CanUnlines [c] where unlines = Prelude.unlines instance Prelude.Eq a => CanIsInfixOf [a] where@@ -66,3 +73,6 @@ instance CanReplicate [i] i Prelude.Int where replicate = Prelude.replicate++instance CanReplicateM [a] a Prelude.Int where+ replicateM = Control.Monad.replicateM
ClassyPrelude/Text.hs view
@@ -11,6 +11,9 @@ import ClassyPrelude.Classes import Data.Text (Text) import qualified Data.Text as T+import qualified Data.Text.Encoding+import qualified Data.Text.Encoding.Error+import Data.ByteString (ByteString) instance CanMapFunc Text Text Char Char where mapFunc = T.map@@ -44,7 +47,11 @@ instance CanWords Text where words = T.words unwords = T.unwords- lines = T.lines++instance CanLinesFunc Text where+ linesFunc = T.lines++instance CanUnlines Text where unlines = T.unlines instance CanSplit Text Char where@@ -65,3 +72,8 @@ instance CanReplicate Text Text Prelude.Int where replicate = T.replicate++instance CanEncodeUtf8Func Text ByteString where+ encodeUtf8Func = Data.Text.Encoding.encodeUtf8+instance CanDecodeUtf8Func ByteString Text where+ decodeUtf8Func = Data.Text.Encoding.decodeUtf8With Data.Text.Encoding.Error.lenientDecode
ClassyPrelude/Vector.hs view
@@ -18,6 +18,8 @@ concatMapFunc = V.concatMap instance CanFilterFunc (Vector a) (Vector a) a where filterFunc = V.filter+instance CanFilterMFunc (Vector a) a where+ filterMFunc = V.filterM instance CanLength (Vector a) Prelude.Int where length = V.length instance CanSingleton (Vector a) a where@@ -51,3 +53,6 @@ instance CanReplicate (Vector a) a Prelude.Int where replicate = V.replicate++instance CanReplicateM (Vector a) a Prelude.Int where+ replicateM = V.replicateM
classy-prelude.cabal view
@@ -1,5 +1,5 @@ name: classy-prelude-version: 0.3.1+version: 0.4.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
test/main.hs view
@@ -11,6 +11,8 @@ import Prelude (asTypeOf, undefined, fromIntegral) import qualified Prelude import Control.Monad.Trans.Writer (tell, Writer, runWriter)+import Data.Maybe (isJust)+import Data.Functor.Identity (runIdentity) dictionaryProps :: ( CanInsertVal a Int Char@@ -90,6 +92,21 @@ prop "filter f c == pack (filter f (unpack c))" $ \c -> (repack (filter f (c `asTypeOf` dummy)) `asTypeOf` dummy) == pack (filter f (unpack c)) +filterMProps :: ( CanPack a i+ , Show a+ , Arbitrary a+ , Eq a+ , CanFilterMFunc a i+ )+ => a+ -> (i -> Bool)+ -> Spec+filterMProps dummy f' = do+ prop "filterM f c == fmap pack (filterM f (unpack c))" $ \c ->+ runIdentity (fmap repack (filterM f (c `asTypeOf` dummy))) `asTypeOf` dummy == runIdentity (fmap pack (filterM f (unpack c)))+ where+ f = return . f'+ lengthProps :: ( Show a , Eq a , Arbitrary a@@ -178,6 +195,42 @@ prop "fromChunks . return . concat . toChunks == id" $ \a -> fromChunks [concat $ toChunks (a `asTypeOf` dummy)] == a +stripSuffixProps :: ( Eq a+ , Monoid a+ , CanStripSuffix a+ , Show a+ , Arbitrary a+ ) => a -> Spec+stripSuffixProps dummy = do+ prop "stripSuffix y (x ++ y) == Just x" $ \x y ->+ stripSuffix y (x ++ y) == Just (x `asTypeOf` dummy)+ prop "isJust (stripSuffix x y) == isSuffixOf x y" $ \x y ->+ isJust (stripSuffix x y) == isSuffixOf x (y `asTypeOf` dummy)++replicateMProps :: ( Eq c+ , Show len+ , Arbitrary len+ , CanReplicateM c i len+ , CanReplicate c i len+ , Show i+ , Arbitrary i+ , Integral len+ ) => c -> Spec+replicateMProps dummy = do+ prop "runIdentity (replicateM i (return x)) == replicate i x" $ \i' x ->+ let i = i' `mod` 20+ in runIdentity (replicateM i (return x)) == (replicate i x `asTypeOf` dummy)++utf8Props :: ( Eq t+ , Show t+ , Arbitrary t+ , CanEncodeUtf8Func t b+ , CanDecodeUtf8Func b t+ ) => t -> Spec+utf8Props dummy = do+ prop "decodeUtf8 . encodeUtf8 == id" $ \t ->+ decodeUtf8 (encodeUtf8 t) == (t `asTypeOf` dummy)+ main :: IO () main = hspec $ do describe "dictionary" $ do@@ -209,6 +262,9 @@ describe "Data.Text.Lazy" $ filterProps (undefined :: LText) (< 'A') describe "Data.Map" $ filterProps (undefined :: Map Int Char) (\(i, _) -> i < 20) describe "Data.HashMap" $ filterProps (undefined :: HashMap Int Char) (\(i, _) -> i < 20)+ describe "filterM" $ do+ describe "list" $ filterMProps (undefined :: [Int]) (< 20)+ describe "Data.Vector" $ filterMProps (undefined :: Vector Int) (< 20) describe "length" $ do describe "list" $ lengthProps (undefined :: [Int]) describe "Data.Vector" $ lengthProps (undefined :: Vector Int)@@ -246,6 +302,17 @@ describe "chunks" $ do describe "ByteString" $ chunkProps (asLByteString undefined) describe "Text" $ chunkProps (asLText undefined)+ describe "stripSuffix" $ do+ describe "Text" $ stripSuffixProps (undefined :: Text)+ describe "LText" $ stripSuffixProps (undefined :: LText)+ describe "ByteString" $ stripSuffixProps (undefined :: ByteString)+ describe "LByteString" $ stripSuffixProps (undefined :: LByteString)+ describe "replicateM" $ do+ describe "list" $ replicateMProps (undefined :: [Int])+ describe "Vector" $ replicateMProps (undefined :: Vector Int)+ describe "encode/decode UTF8" $ do+ describe "Text" $ utf8Props (undefined :: Text)+ describe "LText" $ utf8Props (undefined :: LText) instance Arbitrary (Map Int Char) where arbitrary = fromList <$> arbitrary