packages feed

hydrogen-prelude 0.14 → 0.20

raw patch · 6 files changed

Files

CHANGELOG.md view
@@ -69,7 +69,38 @@  ## v0.11 + Added `nicify` form `Text.Nicify`-+ Upgraded dependency `hydrogen-version` form `>=1.2` to `>=1.3`++ Upgraded dependency `hydrogen-version` from `>=1.2` to `>=1.3`  ## v0.12 + Added `Default`++## v0.13++ _Skipped_++## v0.14++ Aligned with other `hydrogen-*` packages++## v0.15++ Added `Apply`++ Added `uncurry3`, `uncurry4`, `uncurry5`++## v0.16++ Changed `Apply` to use `-XMultiParamTypeClasses` and `-XTypeFamilies`+  for better type inference++ Added `$$`, `$$$`, `$$$$`, `$$$$$` (like `uncurryN`)++ Added `<$$>`, `<$$$>`, `<$$$$>`, `<$$$$$>` (like `<$>` and `uncurryN`)++## v0.17++ Removed instance `MonadPlus m => Default (m a)`.++## v0.18++ Removed dependency on `nicify`++## v0.19++ Removed `Apply` and `Applicator` again++ Lowered dependencies to work with GHC 7.6 and base 4.6 too++## v0.20++ Support for GHC 7.4, 7.6, and 7.8++ Instances for `Serializable` but also for `Binary`+
README.md view
@@ -1,6 +1,8 @@ hydrogen-prelude ================ +[![Build Status](https://travis-ci.org/scravy/hydrogen-prelude.svg?branch=master)](https://travis-ci.org/scravy/hydrogen-prelude)+ + [`about`](#about)   + [`scravy.de/hydrogen-prelude`](http://scravy.de/hydrogen-prelude)   + [`hackage.haskell.org/package/hydrogen-prelude`](http://hackage.haskell.org/package/hydrogen-prelude)@@ -15,6 +17,8 @@   + [`ShowBox`](#showbox--forall-a-show-a--a--showbox)   + [`.|`, `.&`, `.^`](#----a--bool--a--bool--a--bool)   + [`List a`](#type-list-a--a)+  + [`Default a`](#class-default-a)+  + [`Apply a`](#class-apply-a) + [`re-exports`](#re-exports)   + [`Hydrogen.Prelude`](#hydrogenprelude)   + [`Hydrogen.Prelude.IO`](#hydrogenpreludeio)@@ -54,6 +58,8 @@  Beyond existing functions from well-known standard packages, this prelude defines a few utilities (mostly aimed at unifying functionality across different packages, like `containers` and `array`). +---+ ### `(!) :: Has a ⇒ a → HasKey a → HasValue a`  `(!)` is provided for several data types which associate a key and a value.@@ -67,6 +73,8 @@ + `Ord k ⇒ Map k v` with `HasValue → v` + `Ord k ⇒ MultiMap k v` with `HasValue → [v]` +---+ ### `(?) :: Container a ⇒ a → Contained a → Bool`  Check whether the element on the right is contained in the collection on the left.@@ -81,6 +89,8 @@ + `Ord k ⇒ Map k v` with `Contained → k` + `Ord k ⇒ MultiMap k v` with `Contained → k` +---+ ### `tmap`  A little bit like `fmap` but defined differently on some datatypes (applies e.g. to both components of a tuple).@@ -97,42 +107,81 @@ + `Map k v` + `MultiMap k v` +---+ ### `fmap` vs `map`  Hydrogen Prelude exports `fmap` as `map` - the way it ought to be. +---+ ### `__ :: a`  A handy shortcut for `undefined`. +---+ ### FSharp's `|>` (which is `flip ($)`)  Use it to pipe things from one function to the other, left to right:      head xs |> fromEnum |> show +---+ ### `safeHead :: a → [a] → a`  The head of the list, or the default given as first argument.      safeHead x xs = maybe x head . listToMaybe +---+ ### `ShowBox :: forall a. (Show a) ⇒ a → ShowBox` ###  Wrap anything that is showable (can be used to build heterogeneous lists). +---+ ### `.|, .&, .^ :: (a → Bool) → (a → Bool) → (a → Bool)`  Combines predicates.      filter (isDigit .| isLetter) +---+ ### `type List a = [a]` -A shorthand for the type of lists, if you prefer this more wordy version.+A longhand for the type of lists, if you prefer this more wordy version. +---++### `class Default a` ###++A class that provides the `def` function for default values for types.+Instances of `MonadPlus` automatically have an instance where `def = mzero`.++Default instances for most primitive types are also provided.++---++### `class Apply a` ###++Provides the `*$*` operator which is your all-purpose application operator.+It does uncurrying (if you want to apply a tupel result of a function to+a function that is curryied, works with tupels of up to 5 components) and+also works with `Applicative`, i.e. it also does `fmap . uncurry`:++    data Operator = Operator Value OperatorType Value++    parseInfixOperation :: Parser (Value, OperatorType, Value)++    ... Operator *$* parseInfixOperation ...+ re-exports ----------+  ### Hydrogen.Prelude 
Setup.hs view
@@ -1,2 +1,4 @@ import Distribution.Simple+ main = defaultMain+
hydrogen-prelude.cabal view
@@ -1,5 +1,5 @@ name:                 hydrogen-prelude-version:              0.14+version:              0.20 homepage:             http://scravy.de/hydrogen-prelude/ synopsis:             Hydrogen Prelude license:              MIT@@ -12,33 +12,43 @@ cabal-version:        >=1.14  source-repository head-    type:             git-    location:         https://github.com/scravy/hydrogen-prelude+  type:             git+  location:         https://github.com/scravy/hydrogen-prelude +flag explicitText+ library   exposed-modules:    Hydrogen.Prelude                       , Hydrogen.Prelude.IO                       , Hydrogen.Prelude.Network                       , Hydrogen.Prelude.System-  build-depends:      base ==4.7.*-                      , array ==0.5.*-                      , cereal ==0.4.*-                      , containers ==0.5.*-                      , directory ==1.2.*-                      , filepath ==1.3.*-                      , hashable ==1.2.*-                      , hydrogen-multimap ==0.1-                      , hydrogen-version >=1.3-                      , network >=2.4.2.2-                      , nicify-                      , process ==1.2.*-                      , random ==1.0.*-                      , regex-base ==0.93.*-                      , regex-tdfa ==1.2.*-                      , strict ==0.3.*-                      , time ==1.4.*-                      , transformers ==0.3.*-                      , uuid ==1.3.*+  build-depends:      base >=4.5 && <5+                      , array >=0.4+                      , binary >=0.5.1+                      , bytestring >=0.9.2.1+                      , cereal >=0.4.1.1+                      , containers >=0.4.2.1+                      , directory >=1.1+                      , filepath >=1.3+                      , hashable >=1.1+                      , hydrogen-multimap >=0.3+                      , hydrogen-version >=1.4+                      , network >=2.3+                      , process >=1.1.0.1+                      , random >=1.0.1.1+                      , regex-base >=0.93.1+                      , regex-tdfa >=1.2+                      , strict >=0.3+                      , text >=0.11.2+                      , time >=1.4+                      , transformers >=0.3+                      , uuid >=1.3+  if impl(ghc <= 7.6)+    build-depends:    ghc-prim+                      , text <1.2.0.4+  if impl(ghc >= 7.6)+    build-depends:    binary >=0.7+   hs-source-dirs:     src   ghc-options:        -Wall   default-language:   Haskell2010@@ -48,18 +58,13 @@                       , DeriveFunctor                       , DeriveGeneric                       , DeriveTraversable-                      , EmptyCase                       , FlexibleInstances                       , FlexibleContexts                       , GADTs-                      , LambdaCase-                      , MultiWayIf-                      , NegativeLiterals+                      , MultiParamTypeClasses                       , NoImplicitPrelude                       , PackageImports-                      , RankNTypes                       , RecordWildCards                       , ScopedTypeVariables                       , StandaloneDeriving-                      , TupleSections                       , TypeFamilies
src/Hydrogen/Prelude.hs view
@@ -24,7 +24,6 @@   , module Data.Maybe   , module Data.Ord   , module Data.Ratio-  , module Data.Serialize   , module Data.String   , module Data.Time   , module Data.Time.Calendar.OrdinalDate@@ -41,15 +40,37 @@   , (=~)   , (=~~)   , (|>)+  , ($$)+  , ($$$)+  , ($$$$)+  , ($$$$$)+  , (<$$>)+  , (<$$$>)+  , (<$$$$>)+  , (<$$$$$>)   , uuidFromString   , randomUUID-  , nicify   , safeHead   , safeHeadAndTail   , safeHeadAndTail2   , firstJust+  , uncurry3+  , uncurry4+  , uncurry5   , map   , UUID+  , ByteString+  , LazyByteString+  , Serialize+  , encode+  , encodeLazy+  , decode+  , decodeLazy+  , Binary+  , binaryEncode+  , binaryDecode+  , binaryEncodeFile+  , binaryDecodeFile   , Generic   , List   , Map@@ -86,6 +107,10 @@   , sequence   , sequence_   , sum+#if MIN_VERSION_base(4,6,0)+#else+  , catch+#endif   )  import "base" Control.Applicative@@ -103,8 +128,12 @@ import "array" Data.Array hiding ((!)) import qualified "array" Data.Array as Array +import "binary" Data.Binary (Binary)+import qualified "binary" Data.Binary as Binary import "base" Data.Bits hiding (bitSize) import "base" Data.Bool+import "bytestring" Data.ByteString (ByteString)+import qualified "bytestring" Data.ByteString.Lazy as LazyByteString import "base" Data.Char import "base" Data.Complex import "base" Data.Dynamic@@ -145,7 +174,8 @@ import "base" Data.Maybe import "base" Data.Ord import "base" Data.Ratio-import "cereal" Data.Serialize+import "cereal" Data.Serialize (Serialize)+import qualified "cereal" Data.Serialize as Serialize import "base" Data.String import "time" Data.Time import "time" Data.Time.Calendar.OrdinalDate@@ -154,13 +184,16 @@ import "base" Data.Typeable import "base" Data.Word +#if MIN_VERSION_base(4,6,0) import "base" GHC.Generics (Generic)+#else+import "ghc-prim" GHC.Generics (Generic)+#endif  import "base" Numeric  import "base" Text.Printf import "regex-tdfa" Text.Regex.TDFA-import "nicify" Text.Nicify (nicify)  import "containers" Data.Map (Map) import qualified "containers" Data.Map as Map@@ -178,6 +211,17 @@ import qualified "uuid" Data.UUID.V4  +-----------------------------------------------------------------------+-- Lazy type aliases+-----------------------------------------------------------------------++type LazyByteString = LazyByteString.ByteString+++-----------------------------------------------------------------------+-- Generic instances+-----------------------------------------------------------------------+ deriving instance Eq ZonedTime deriving instance Generic Day deriving instance Generic LocalTime@@ -186,39 +230,129 @@ deriving instance Generic UniversalTime deriving instance Generic ZonedTime ++-----------------------------------------------------------------------+-- Serialize & Binary instances+-----------------------------------------------------------------------+ instance Serialize Day-instance Serialize LocalTime-instance Serialize TimeOfDay+instance Binary Day+ instance Serialize TimeZone+instance Binary TimeZone+ instance Serialize UniversalTime+instance Binary UniversalTime+ instance Serialize Version+instance Binary Version++#if MIN_VERSION_base(4,7,0)+instance Serialize LocalTime+instance Binary LocalTime++instance Serialize TimeOfDay+instance Binary TimeOfDay+ instance Serialize ZonedTime+instance Binary ZonedTime  instance Serialize (Fixed E12) where-    put (MkFixed int) = put int+    put (MkFixed int) = Serialize.put int -    get = MkFixed <$> get+    get = MkFixed <$> Serialize.get +instance Binary (Fixed E12) where+    put (MkFixed int) = Binary.put int++    get = MkFixed <$> Binary.get+#endif+ instance Serialize UUID where -    put uuid = do-        let p = putWord32be-            (w1, w2, w3, w4) = Data.UUID.toWords uuid-        p w1 >> p w2 >> p w3 >> p w4+    put uuid = p w1 >> p w2 >> p w3 >> p w4+      where+        p = Serialize.putWord32be+        (w1, w2, w3, w4) = Data.UUID.toWords uuid -    get = let g = getWord32be in liftM4 Data.UUID.fromWords g g g g-      +    get = liftM4 Data.UUID.fromWords g g g g+      where+        g = Serialize.getWord32be++-- instance Binary UUID is already provided by UUID package+++-----------------------------------------------------------------------+-- Data.Serialize+-----------------------------------------------------------------------++encode :: Serialize a => a -> ByteString+-- ^ Encode a value using binary serialization to a strict ByteString.+encode = Serialize.encode++encodeLazy :: Serialize a => a -> LazyByteString+-- ^ Encode a value using binary serialization to a lazy ByteString.+encodeLazy = Serialize.encodeLazy++decode :: Serialize a => ByteString -> Either String a+-- ^ Decode a value from a strict ByteString, reconstructing the+-- original structure.+decode = Serialize.decode++decodeLazy :: Serialize a => LazyByteString -> Either String a+-- ^ Decode a value from a lazy ByteString, reconstructing the+-- original structure.+decodeLazy = Serialize.decodeLazy+++-----------------------------------------------------------------------+-- Data.Binary+-----------------------------------------------------------------------++binaryEncode :: Binary a => a -> LazyByteString+-- ^ Encode a value using binary serialisation to a lazy ByteString.+binaryEncode = Binary.encode++binaryDecode :: Binary a => LazyByteString -> a+-- ^ Decode a value from a lazy ByteString, reconstructing the+-- original structure.+binaryDecode = Binary.decode++binaryEncodeFile :: Binary a => FilePath -> a -> IO ()+-- ^ Lazily serialise a value to a file.+binaryEncodeFile = Binary.encodeFile++binaryDecodeFile :: Binary a => FilePath -> IO a+-- ^ Decode a value from a file. In case of errors, error will be+-- called with the error message.+binaryDecodeFile = Binary.decodeFile+++-----------------------------------------------------------------------+-- ShowBox+-----------------------------------------------------------------------+ data ShowBox where     ShowBox :: forall a. (Show a) => a -> ShowBox  instance Show ShowBox where     show (ShowBox a) = show a ++-----------------------------------------------------------------------+-- Composition of boolean functions+-----------------------------------------------------------------------+ (.|), (.&), (.^) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool) f .| g = \x -> f x || g x f .& g = \x -> f x && g x f .^ g = \x -> f x /= g x ++-----------------------------------------------------------------------+-- Nice shorthands & operators+-----------------------------------------------------------------------+ (|>) :: a -> (a -> b) -> b -- ^ @flip ('$')@ (|>) = flip ($)@@ -227,6 +361,11 @@ -- ^ A shorthand for 'undefined'. __ = error "Hydrogen.Prelude.undefined" ++-----------------------------------------------------------------------+-- UUID functions+-----------------------------------------------------------------------+ uuidFromString :: String -> Maybe UUID uuidFromString = Data.UUID.fromString @@ -234,26 +373,36 @@ -- ^ Produces a random V4 UUID (alias for 'Data.UUID.V4.nextRandom'). randomUUID = Data.UUID.V4.nextRandom ++-----------------------------------------------------------------------+-- Safe functions+-----------------------------------------------------------------------+ safeHead     :: a   -- ^ The default value for the case of the empty list.     -> [a] -- ^ The list.     -> a -- ^ Returns the head of the list or the default value.-safeHead default_ = \case+safeHead default_ = \z -> case z of     x : _ -> x     _     -> default_  safeHeadAndTail :: a -> [a] -> (a, [a])-safeHeadAndTail default_ = \case+safeHeadAndTail default_ = \z -> case z of     x : xs -> (x, xs)     _ -> (default_, [])  safeHeadAndTail2 :: a -> a -> [a] -> (a, a, [a])-safeHeadAndTail2 d1 d2 = \case+safeHeadAndTail2 d1 d2 = \z -> case z of     x : y : xs -> (x, y, xs)     x : xs -> (x, d2, xs)     xs -> (d1, d2, xs) ++-----------------------------------------------------------------------+-- firstJust+-----------------------------------------------------------------------+ firstJust :: [a -> Maybe b] -> a -> Maybe b -- ^ Applies a bunch of functions on a given value, --   returns the first result that is not Nothing@@ -263,6 +412,11 @@     x -> x firstJust [] _ = Nothing ++-----------------------------------------------------------------------+-- More generic maps+-----------------------------------------------------------------------+ map :: Functor f => (a -> b) -> f a -> f b -- ^ map as it should be: 'fmap'. map = fmap@@ -325,8 +479,17 @@     tmap = fmap  +-----------------------------------------------------------------------+-- Verbose `List' type+-----------------------------------------------------------------------+ type List a = [a] ++-----------------------------------------------------------------------+-- Has+-----------------------------------------------------------------------+ class Has a where      type HasKey a@@ -366,6 +529,10 @@     (!) = flip MultiMap.lookup  +-----------------------------------------------------------------------+-- Container+-----------------------------------------------------------------------+ class Container a where      type Contained a@@ -404,6 +571,69 @@     (?) = flip MultiMap.member  +-----------------------------------------------------------------------+-- Default+-----------------------------------------------------------------------+ class Default a where      def :: a++instance Default Int where def = 0+instance Default Int8 where def = 0+instance Default Int16 where def = 0+instance Default Int32 where def = 0+instance Default Int64 where def = 0+instance Default Word8 where def = 0+instance Default Word16 where def = 0+instance Default Word32 where def = 0+instance Default Word64 where def = 0+instance Default Integer where def = 0++instance Default Bool where def = False+instance Default [a] where def = []+instance Default (Maybe a) where def = Nothing+++-----------------------------------------------------------------------+-- Apply / curry operators+-----------------------------------------------------------------------++infixr 0 $$+infixr 0 $$$+infixr 0 $$$$+infixr 0 $$$$$++($$) :: (a -> b -> z) -> (a, b) -> z+($$) = uncurry++($$$), uncurry3 :: (a -> b -> c -> z) -> (a, b, c) -> z+uncurry3 f (a, b, c) = f a b c+($$$) = uncurry3++($$$$), uncurry4 :: (a -> b -> c -> d -> z) -> (a, b, c, d) -> z+uncurry4 f (a, b, c, d) = f a b c d+($$$$) = uncurry4++($$$$$), uncurry5 :: (a -> b -> c -> d -> e -> z) -> (a, b, c, d, e) -> z+uncurry5 f (a, b, c, d, e) = f a b c d e+($$$$$) = uncurry5+++infixl 4 <$$>+infixl 4 <$$$>+infixl 4 <$$$$>+infixl 4 <$$$$$>++(<$$>) :: Functor f => (a -> b -> z) -> f (a, b) -> f z+(<$$>) = (<$>) . uncurry++(<$$$>) :: Functor f => (a -> b -> c -> z) -> f (a, b, c) -> f z+(<$$$>) = (<$>) . uncurry3++(<$$$$>) :: Functor f => (a -> b -> c -> d -> z) -> f (a, b, c, d) -> f z+(<$$$$>) = (<$>) . uncurry4++(<$$$$$>) :: Functor f => (a -> b -> c -> d -> e -> z) -> f (a, b, c, d, e) -> f z+(<$$$$$>) = (<$>) . uncurry5+
src/Hydrogen/Prelude/System.hs view
@@ -49,25 +49,25 @@   where      find :: Set FilePath -> c -> FilePath -> IO (Set FilePath, [(FilePath, c)])-    find visited context dir = do+    find visited context dir = canonicalizePath dir >>= find'+      where+        find' thisDirectory+          | Set.member thisDirectory visited = return (Set.empty, [])+          | otherwise = do -      thisDirectory <- canonicalizePath dir-      if | Set.member thisDirectory visited -> return (Set.empty, [])-         | otherwise -> do+                allFiles <- map (dir </>) <$> getDirectoryContents dir+                theFiles <- filterFiles allFiles+                theDirs  <- filterM isDir allFiles+                context' <- updater context dir theFiles -            allFiles <- map (dir </>) <$> getDirectoryContents dir-            theFiles <- filterFiles allFiles-            theDirs  <- filterM isDir allFiles-            context' <- updater context dir theFiles+                let visited' = Set.insert thisDirectory visited+                    f (visited, files) dir = do+                        (visited', files') <- find visited context' dir+                        return (visited', files' : files) -            let visited' = Set.insert thisDirectory visited-                f (visited, files) dir = do-                    (visited', files') <- find visited context' dir-                    return (visited', files' : files)+                (visited'', files') <- foldM f (visited', []) theDirs -            (visited'', files') <- foldM f (visited', []) theDirs-            -            return (visited'', concat (zip theFiles (repeat context') : files'))+                return (visited'', concat (zip theFiles (repeat context') : files'))      filterFiles = filterM (\x -> liftM2 (&&) (doesFileExist x) (predicate x))     isDir x = liftM2 (&&) (doesDirectoryExist x) (return (head (takeFileName x) /= '.'))@@ -77,10 +77,10 @@ escapeFileName s = case s of     ('/' : xs)         -> '_' : escapeFileName xs-    (x : xs) ->-      if | isSafeChar x -> x : escapeFileName xs-         | ord x <= 255 -> '$' : printf "%02X" (ord x) ++ escapeFileName xs-         | otherwise    -> "$$" ++ printf "%04X" (ord x) ++ escapeFileName xs+    (x : xs)+      | isSafeChar x -> x : escapeFileName xs+      | ord x <= 255 -> '$' : printf "%02X" (ord x) ++ escapeFileName xs+      | otherwise    -> "$$" ++ printf "%04X" (ord x) ++ escapeFileName xs     [] -> []   where     isSafeChar x = isAscii x && isAlphaNum x || x `elem` ".-"