packages feed

managed 1.0.1 → 1.0.2

raw patch · 5 files changed

+283/−283 lines, 5 filessetup-changedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Control.Monad.Managed: instance Applicative Managed
- Control.Monad.Managed: instance Floating a => Floating (Managed a)
- Control.Monad.Managed: instance Fractional a => Fractional (Managed a)
- Control.Monad.Managed: instance Functor Managed
- Control.Monad.Managed: instance Monad Managed
- Control.Monad.Managed: instance MonadIO Managed
- Control.Monad.Managed: instance Monoid a => Monoid (Managed a)
- Control.Monad.Managed: instance Num a => Num (Managed a)
+ Control.Monad.Managed: instance Control.Monad.IO.Class.MonadIO Control.Monad.Managed.Managed
+ Control.Monad.Managed: instance GHC.Base.Applicative Control.Monad.Managed.Managed
+ Control.Monad.Managed: instance GHC.Base.Functor Control.Monad.Managed.Managed
+ Control.Monad.Managed: instance GHC.Base.Monad Control.Monad.Managed.Managed
+ Control.Monad.Managed: instance GHC.Base.Monoid a => GHC.Base.Monoid (Control.Monad.Managed.Managed a)
+ Control.Monad.Managed: instance GHC.Float.Floating a => GHC.Float.Floating (Control.Monad.Managed.Managed a)
+ Control.Monad.Managed: instance GHC.Num.Num a => GHC.Num.Num (Control.Monad.Managed.Managed a)
+ Control.Monad.Managed: instance GHC.Real.Fractional a => GHC.Real.Fractional (Control.Monad.Managed.Managed a)

Files

LICENSE view
@@ -1,24 +1,24 @@-Copyright (c) 2014 Gabriel Gonzalez-All rights reserved.--Redistribution and use in source and binary forms, with or without modification,-are permitted provided that the following conditions are met:-    * Redistributions of source code must retain the above copyright notice,-      this list of conditions and the following disclaimer.-    * Redistributions in binary form must reproduce the above copyright notice,-      this list of conditions and the following disclaimer in the documentation-      and/or other materials provided with the distribution.-    * Neither the name of Gabriel Gonzalez nor the names of other contributors-      may be used to endorse or promote products derived from this software-      without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+Copyright (c) 2014 Gabriel Gonzalez
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of Gabriel Gonzalez nor the names of other contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple-main = defaultMain+import Distribution.Simple
+main = defaultMain
managed.cabal view
@@ -1,40 +1,40 @@-Name: managed-Version: 1.0.1-Cabal-Version: >=1.8.0.2-Build-Type: Simple-License: BSD3-License-File: LICENSE-Copyright: 2014 Gabriel Gonzalez-Author: Gabriel Gonzalez-Maintainer: Gabriel439@gmail.com-Bug-Reports: https://github.com/Gabriel439/Haskell-Managed-Library/issues-Synopsis: A monad for managed values-Description: In Haskell you very often acquire values using the @with...@-  idiom using functions of type @(a -> IO r) -> IO r@.  This idiom forms a-  @Monad@, which is a special case of the @ContT@ monad (from @transformers@) or-  the @Codensity@ monad (from @kan-extensions@).  The main purpose behind this-  package is to provide a restricted form of these monads specialized to this-  unusually common case.-  .-  The reason this package defines a specialized version of these types is to:-  .-  * be more beginner-friendly,-  .-  * simplify inferred types and error messages, and:-  .-  * provide some additional type class instances that would otherwise be orphan-    instances-Category: Control-Source-Repository head-    Type: git-    Location: https://github.com/Gabriel439/Haskell-Managed-Library--Library-    Hs-Source-Dirs: src-    Build-Depends:-        base              >= 4       && < 5  ,-        transformers      >= 0.2.0.0 && < 0.5 -    Exposed-Modules:-        Control.Monad.Managed,-        Control.Monad.Managed.Safe-    GHC-Options: -O2 -Wall+Name: managed
+Version: 1.0.2
+Cabal-Version: >=1.8.0.2
+Build-Type: Simple
+License: BSD3
+License-File: LICENSE
+Copyright: 2014 Gabriel Gonzalez
+Author: Gabriel Gonzalez
+Maintainer: Gabriel439@gmail.com
+Bug-Reports: https://github.com/Gabriel439/Haskell-Managed-Library/issues
+Synopsis: A monad for managed values
+Description: In Haskell you very often acquire values using the @with...@
+  idiom using functions of type @(a -> IO r) -> IO r@.  This idiom forms a
+  @Monad@, which is a special case of the @ContT@ monad (from @transformers@) or
+  the @Codensity@ monad (from @kan-extensions@).  The main purpose behind this
+  package is to provide a restricted form of these monads specialized to this
+  unusually common case.
+  .
+  The reason this package defines a specialized version of these types is to:
+  .
+  * be more beginner-friendly,
+  .
+  * simplify inferred types and error messages, and:
+  .
+  * provide some additional type class instances that would otherwise be orphan
+    instances
+Category: Control
+Source-Repository head
+    Type: git
+    Location: https://github.com/Gabriel439/Haskell-Managed-Library
+
+Library
+    Hs-Source-Dirs: src
+    Build-Depends:
+        base              >= 4.5     && < 5  ,
+        transformers      >= 0.2.0.0 && < 0.5 
+    Exposed-Modules:
+        Control.Monad.Managed,
+        Control.Monad.Managed.Safe
+    GHC-Options: -O2 -Wall
src/Control/Monad/Managed.hs view
@@ -1,183 +1,183 @@-{-# LANGUAGE RankNTypes #-}--{-| An example Haskell program to copy data from one handle to another might-    look like this:--> main =->     withFile "inFile.txt" ReadMode $ \inHandle ->->         withFile "outFile.txt" WriteMode $ \outHandle ->->             copy inHandle outHandle->-> -- A hypothetical function that copies data from one handle to another-> copy :: Handle -> Handle -> IO ()--    `System.IO.withFile` is one of many functions that acquire some resource in-    an exception-safe way.  These functions take a callback function as an-    argument and they invoke the callback on the resource when it becomes-    available, guaranteeing that the resource is properly disposed if the-    callback throws an exception.--    These functions usually have a type that ends with the following pattern:-->                    Callback-> --                ------------> withXXX :: ... -> (a -> IO r) -> IO r--    Here are some examples of this pattern from the @base@ libraries:--> withArray      :: Storable a => [a] -> (Ptr a   -> IO r) -> IO r-> withBuffer     ::          Buffer e -> (Ptr e   -> IO r) -> IO r-> withCAString   ::            String -> (CString -> IO r) -> IO r-> withForeignPtr ::      ForeignPtr a -> (Ptr a   -> IO r) -> IO r-> withMVar       ::            Mvar a -> (a       -> IO r) -> IO r-> withPool       ::                      (Pool    -> IO r) -> IO r--    Acquiring multiple resources in this way requires nesting callbacks.-    However, you can wrap anything of the form @((a -> IO r) -> IO r)@ in the-    `Managed` monad, which translates binds to callbacks for you:--> import Control.Monad.Managed-> import System.IO->-> inFile :: FilePath -> Managed Handle-> inFile filePath = managed (withFile filePath ReadMode)->-> outFile :: FilePath -> Managed Handle-> outFile filePath = managed (withFile filePath WriteMode)->-> main = runManaged $ do->     inHandle  <- inFile "inFile.txt"->     outHandle <- outFile "outFile.txt"->     liftIO (copy inHandle outHandle)--    ... or you can just wrap things inline:--> main = runManaged $ do->     inHandle  <- managed (withFile "inFile.txt" ReadMode)->     outHandle <- managed (withFile "outFile.txt" WriteMode)->     liftIO (copy inHandle outHandle)--    Additionally, since `Managed` is a `Monad`, you can take advantage of all-    your favorite combinators from "Control.Monad".  For example, the-    `Foreign.Marshal.Utils.withMany` function from "Foreign.Marshal.Utils"-    becomes a trivial wrapper around `mapM`:--> withMany :: (a -> (b -> IO r) -> IO r) -> [a] -> ([b] -> IO r) -> IO r-> withMany f = with . mapM (Managed . f)--    Another reason to use `Managed` is that if you wrap a `Monoid` value in-    `Managed` you get back a new `Monoid`:--> instance Monoid a => Monoid (Managed a)--    This lets you combine managed resources transparently.  You can also lift-    operations from some numeric type classes this way, too, such as the `Num`-    type class.--}--module Control.Monad.Managed (-    -- * Managed-    Managed,-    managed,-    managed_,-    with,-    runManaged,--    -- * Re-exports-    -- $reexports-    module Control.Monad.IO.Class-    ) where--import Control.Applicative (Applicative(pure, (<*>)), liftA2)-import Control.Monad.IO.Class (MonadIO(liftIO))-import Data.Monoid (Monoid(mempty, mappend))---- | A managed resource that you acquire using `with`-newtype Managed a = Managed { (>>-) :: forall r . (a -> IO r) -> IO r }--instance Functor Managed where-    fmap f mx = Managed (\return_ ->-        mx >>- \x ->-        return_ (f x) )--instance Applicative Managed where-    pure r    = Managed (\return_ ->-        return_ r )--    mf <*> mx = Managed (\return_ ->-        mf >>- \f ->-        mx >>- \x ->-        return_ (f x) )--instance Monad Managed where-    return r = Managed (\return_ ->-        return_ r )--    ma >>= f = Managed (\return_ ->-        ma  >>- \a ->-        f a >>- \b ->-        return_ b )--instance MonadIO Managed where-    liftIO m = Managed (\return_ -> do-        a <- m-        return_ a )--instance Monoid a => Monoid (Managed a) where-    mempty = pure mempty--    mappend = liftA2 mappend--instance Num a => Num (Managed a) where-    fromInteger = pure . fromInteger-    negate = fmap negate-    abs    = fmap abs-    signum = fmap signum-    (+) = liftA2 (+)-    (*) = liftA2 (*)-    (-) = liftA2 (-)--instance Fractional a => Fractional (Managed a) where-    fromRational = pure . fromRational-    recip = fmap recip-    (/) = liftA2 (/)--instance Floating a => Floating (Managed a) where-    pi = pure pi-    exp   = fmap exp-    sqrt  = fmap sqrt-    log   = fmap log-    sin   = fmap sin-    tan   = fmap tan-    cos   = fmap cos-    asin  = fmap sin-    atan  = fmap atan-    acos  = fmap acos-    sinh  = fmap sinh-    tanh  = fmap tanh-    cosh  = fmap cosh-    asinh = fmap asinh-    atanh = fmap atanh-    acosh = fmap acosh-    (**)    = liftA2 (**)-    logBase = liftA2 logBase---- | Build a `Managed` value-managed :: (forall r . (a -> IO r) -> IO r) -> Managed a-managed = Managed---- | Like 'managed' but for resource-less operations.-managed_ :: (forall r. IO r -> IO r) -> Managed ()-managed_ f = managed $ \g -> f $ g ()---- | Acquire a `Managed` value-with :: Managed a -> (a -> IO r) -> IO r-with = (>>-)---- | Run a `Managed` computation, enforcing that no acquired resources leak-runManaged :: Managed () -> IO ()-runManaged m = m >>- return--{- $reexports-    "Control.Monad.IO.Class" re-exports 'MonadIO'--}+{-# LANGUAGE RankNTypes #-}
+
+{-| An example Haskell program to copy data from one handle to another might
+    look like this:
+
+> main =
+>     withFile "inFile.txt" ReadMode $ \inHandle ->
+>         withFile "outFile.txt" WriteMode $ \outHandle ->
+>             copy inHandle outHandle
+>
+> -- A hypothetical function that copies data from one handle to another
+> copy :: Handle -> Handle -> IO ()
+
+    `System.IO.withFile` is one of many functions that acquire some resource in
+    an exception-safe way.  These functions take a callback function as an
+    argument and they invoke the callback on the resource when it becomes
+    available, guaranteeing that the resource is properly disposed if the
+    callback throws an exception.
+
+    These functions usually have a type that ends with the following pattern:
+
+>                    Callback
+> --                -----------
+> withXXX :: ... -> (a -> IO r) -> IO r
+
+    Here are some examples of this pattern from the @base@ libraries:
+
+> withArray      :: Storable a => [a] -> (Ptr a   -> IO r) -> IO r
+> withBuffer     ::          Buffer e -> (Ptr e   -> IO r) -> IO r
+> withCAString   ::            String -> (CString -> IO r) -> IO r
+> withForeignPtr ::      ForeignPtr a -> (Ptr a   -> IO r) -> IO r
+> withMVar       ::            Mvar a -> (a       -> IO r) -> IO r
+> withPool       ::                      (Pool    -> IO r) -> IO r
+
+    Acquiring multiple resources in this way requires nesting callbacks.
+    However, you can wrap anything of the form @((a -> IO r) -> IO r)@ in the
+    `Managed` monad, which translates binds to callbacks for you:
+
+> import Control.Monad.Managed
+> import System.IO
+>
+> inFile :: FilePath -> Managed Handle
+> inFile filePath = managed (withFile filePath ReadMode)
+>
+> outFile :: FilePath -> Managed Handle
+> outFile filePath = managed (withFile filePath WriteMode)
+>
+> main = runManaged $ do
+>     inHandle  <- inFile "inFile.txt"
+>     outHandle <- outFile "outFile.txt"
+>     liftIO (copy inHandle outHandle)
+
+    ... or you can just wrap things inline:
+
+> main = runManaged $ do
+>     inHandle  <- managed (withFile "inFile.txt" ReadMode)
+>     outHandle <- managed (withFile "outFile.txt" WriteMode)
+>     liftIO (copy inHandle outHandle)
+
+    Additionally, since `Managed` is a `Monad`, you can take advantage of all
+    your favorite combinators from "Control.Monad".  For example, the
+    `Foreign.Marshal.Utils.withMany` function from "Foreign.Marshal.Utils"
+    becomes a trivial wrapper around `mapM`:
+
+> withMany :: (a -> (b -> IO r) -> IO r) -> [a] -> ([b] -> IO r) -> IO r
+> withMany f = with . mapM (Managed . f)
+
+    Another reason to use `Managed` is that if you wrap a `Monoid` value in
+    `Managed` you get back a new `Monoid`:
+
+> instance Monoid a => Monoid (Managed a)
+
+    This lets you combine managed resources transparently.  You can also lift
+    operations from some numeric type classes this way, too, such as the `Num`
+    type class.
+-}
+
+module Control.Monad.Managed (
+    -- * Managed
+    Managed,
+    managed,
+    managed_,
+    with,
+    runManaged,
+
+    -- * Re-exports
+    -- $reexports
+    module Control.Monad.IO.Class
+    ) where
+
+import Control.Applicative (Applicative(pure, (<*>)), liftA2)
+import Control.Monad.IO.Class (MonadIO(liftIO))
+import Data.Monoid (Monoid(mempty, mappend))
+
+-- | A managed resource that you acquire using `with`
+newtype Managed a = Managed { (>>-) :: forall r . (a -> IO r) -> IO r }
+
+instance Functor Managed where
+    fmap f mx = Managed (\return_ ->
+        mx >>- \x ->
+        return_ (f x) )
+
+instance Applicative Managed where
+    pure r    = Managed (\return_ ->
+        return_ r )
+
+    mf <*> mx = Managed (\return_ ->
+        mf >>- \f ->
+        mx >>- \x ->
+        return_ (f x) )
+
+instance Monad Managed where
+    return r = Managed (\return_ ->
+        return_ r )
+
+    ma >>= f = Managed (\return_ ->
+        ma  >>- \a ->
+        f a >>- \b ->
+        return_ b )
+
+instance MonadIO Managed where
+    liftIO m = Managed (\return_ -> do
+        a <- m
+        return_ a )
+
+instance Monoid a => Monoid (Managed a) where
+    mempty = pure mempty
+
+    mappend = liftA2 mappend
+
+instance Num a => Num (Managed a) where
+    fromInteger = pure . fromInteger
+    negate = fmap negate
+    abs    = fmap abs
+    signum = fmap signum
+    (+) = liftA2 (+)
+    (*) = liftA2 (*)
+    (-) = liftA2 (-)
+
+instance Fractional a => Fractional (Managed a) where
+    fromRational = pure . fromRational
+    recip = fmap recip
+    (/) = liftA2 (/)
+
+instance Floating a => Floating (Managed a) where
+    pi = pure pi
+    exp   = fmap exp
+    sqrt  = fmap sqrt
+    log   = fmap log
+    sin   = fmap sin
+    tan   = fmap tan
+    cos   = fmap cos
+    asin  = fmap sin
+    atan  = fmap atan
+    acos  = fmap acos
+    sinh  = fmap sinh
+    tanh  = fmap tanh
+    cosh  = fmap cosh
+    asinh = fmap asinh
+    atanh = fmap atanh
+    acosh = fmap acosh
+    (**)    = liftA2 (**)
+    logBase = liftA2 logBase
+
+-- | Build a `Managed` value
+managed :: (forall r . (a -> IO r) -> IO r) -> Managed a
+managed = Managed
+
+-- | Like 'managed' but for resource-less operations.
+managed_ :: (forall r. IO r -> IO r) -> Managed ()
+managed_ f = managed $ \g -> f $ g ()
+
+-- | Acquire a `Managed` value
+with :: Managed a -> (a -> IO r) -> IO r
+with = (>>-)
+
+-- | Run a `Managed` computation, enforcing that no acquired resources leak
+runManaged :: Managed () -> IO ()
+runManaged m = m >>- return
+
+{- $reexports
+    "Control.Monad.IO.Class" re-exports 'MonadIO'
+-}
src/Control/Monad/Managed/Safe.hs view
@@ -1,34 +1,34 @@-{-# LANGUAGE RankNTypes #-}--{-| This module is a safer subset of "Control.Monad.Managed" that only lets you-    unwrap the `Managed` type using `runManaged`.  This enforces that you never-    leak acquired resources from a `Managed` computation.--    In general, you should strive to propagate the `Managed` type as much as-    possible and use `runManaged` when you are done with acquired resources.-    However, there are legitimate circumstances where you want to return a value-    other than acquired resource from the bracketed computation, which requires-    using `Control.Monad.Managed.with`.--    This module is not the default because you can also use the `Managed` type-    for callback-based code that is completely unrelated to resources.--}--module Control.Monad.Managed.Safe (-    -- * Managed-    Managed,-    managed,-    managed_,-    runManaged,--    -- * Re-exports-    -- $reexports-    module Control.Monad.IO.Class-    ) where--import Control.Monad.IO.Class (MonadIO(liftIO))-import Control.Monad.Managed (Managed, managed, managed_, runManaged)--{- $reexports-    "Control.Monad.IO.Class" re-exports 'MonadIO'--}+{-# LANGUAGE RankNTypes #-}
+
+{-| This module is a safer subset of "Control.Monad.Managed" that only lets you
+    unwrap the `Managed` type using `runManaged`.  This enforces that you never
+    leak acquired resources from a `Managed` computation.
+
+    In general, you should strive to propagate the `Managed` type as much as
+    possible and use `runManaged` when you are done with acquired resources.
+    However, there are legitimate circumstances where you want to return a value
+    other than acquired resource from the bracketed computation, which requires
+    using `Control.Monad.Managed.with`.
+
+    This module is not the default because you can also use the `Managed` type
+    for callback-based code that is completely unrelated to resources.
+-}
+
+module Control.Monad.Managed.Safe (
+    -- * Managed
+    Managed,
+    managed,
+    managed_,
+    runManaged,
+
+    -- * Re-exports
+    -- $reexports
+    module Control.Monad.IO.Class
+    ) where
+
+import Control.Monad.IO.Class (MonadIO(liftIO))
+import Control.Monad.Managed (Managed, managed, managed_, runManaged)
+
+{- $reexports
+    "Control.Monad.IO.Class" re-exports 'MonadIO'
+-}