exitcode 0.1.0.0 → 0.1.0.1
raw patch · 6 files changed
+121/−79 lines, 6 filesdep +hedgehogdep +mmorphdep +tasty-hedgehogdep ~QuickCheckdep ~basedep ~lensPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: hedgehog, mmorph, tasty-hedgehog
Dependency ranges changed: QuickCheck, base, lens, semigroupoids, semigroups, tasty, tasty-hunit, tasty-quickcheck
API changes (from Hackage documentation)
+ Control.Exitcode: instance Control.Monad.Morph.MFunctor Control.Exitcode.ExitcodeT
+ Control.Exitcode: instance Control.Monad.Morph.MMonad Control.Exitcode.ExitcodeT
- Control.Exitcode: _ExitSuccess :: Prism' Exitcode0 ()
+ Control.Exitcode: _ExitSuccess :: Prism' (Exitcode a) a
Files
- LICENCE +31/−0
- LICENSE +0/−31
- changelog.md +6/−0
- exitcode.cabal +16/−13
- src/Control/Exitcode.hs +43/−15
- test/Tests.hs +25/−20
+ LICENCE view
@@ -0,0 +1,31 @@+Copyright (c) 2017,2018, Commonwealth Scientific and Industrial Research Organisation+(CSIRO) ABN 41 687 119 230.++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 QFPL 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.
− LICENSE
@@ -1,31 +0,0 @@-Copyright (c) 2017, Commonwealth Scientific and Industrial Research Organisation-(CSIRO) ABN 41 687 119 230.--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 QFPL 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.
changelog.md view
@@ -1,3 +1,9 @@+0.1.0.1++* Make `_ExitSuccess` more polymorphic. It was unnecessarily specialised to `()`.+* Use `NoImplicitPrelude` and explicit imports.+* Depend on `mmorph` and implement instances for `MFunctor` and `MMonad`.+ 0.1.0.0 * This change log starts.
exitcode.cabal view
@@ -1,24 +1,24 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: exitcode-version: 0.1.0.0+version: 0.1.0.1 synopsis: Monad transformer for exit codes description: <<http://i.imgur.com/uZnp9ke.png>> . Monad transformer for exit codes-homepage: https://github.com/qfpl/exitcode license: BSD3-license-file: LICENSE+license-file: LICENCE author: Queensland Functional Programming Lab <oᴉ˙ldɟb@llǝʞsɐɥ> maintainer: Queensland Functional Programming Lab <oᴉ˙ldɟb@llǝʞsɐɥ>-copyright: Copyright (C) 2017 Commonwealth Scientific and Industrial Research Organisation (CSIRO)+copyright: Copyright (C) 2017,2018 Commonwealth Scientific and Industrial Research Organisation (CSIRO) category: Control build-type: Simple extra-source-files: changelog.md cabal-version: >=1.10 homepage: https://github.com/qfpl/exitcode bug-reports: https://github.com/qfpl/exitcode/issues+tested-with: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1 source-repository head type: git@@ -26,25 +26,28 @@ library exposed-modules: Control.Exitcode- build-depends: base >=4.8 && <4.10- , lens >=4.15 && <4.16+ build-depends: base >=4.8 && <4.11+ , lens >=4.15 && < 4.17+ , mmorph >= 1.0 && < 1.2 , mtl >=2.2 && <2.3 , semigroupoids >=5.1 && <5.3- , semigroups >=0.18 && <0.19+ , semigroups >=0.16 && <0.19 , transformers >=0.4.1 && <5.5 hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall test-suite tests- build-depends: QuickCheck >=2.9.2 && <2.11- , base >=4.8 && <4.10+ build-depends: QuickCheck >=2.9.2 && <2.12+ , base >=4.8 && <4.11 , checkers >=0.4.6 && <0.5 , exitcode- , lens >=4.15 && <4.16- , tasty >=0.11 && <0.12- , tasty-hunit >=0.9 && <0.10- , tasty-quickcheck >=0.8.4 && <0.10+ , hedgehog >=0.5 && <0.6+ , lens >=4.15 && <4.17+ , tasty >=0.11 && <1.1+ , tasty-hunit >=0.9 && <0.11+ , tasty-hedgehog >= 0.1 && <0.3+ , tasty-quickcheck >=0.8.4 && <0.11 , transformers >=0.4.1 && <5.5 type: exitcode-stdio-1.0 main-is: Tests.hs
src/Control/Exitcode.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TupleSections #-}@@ -23,26 +24,30 @@ , _ExitSuccess ) where -# if MIN_VERSION_base(4,9,0)-import Control.Applicative (Applicative, liftA2)-# else-import Control.Applicative (liftA2)-# endif+import Control.Applicative (Applicative(pure, (<*>)), liftA2)+import Control.Category ((.)) import Control.Lens (Iso, Prism', iso, prism', view, (^?), _Left, _Right)+import Control.Monad (Monad(return, (>>=))) import Control.Monad.Cont.Class (MonadCont (..)) import Control.Monad.Error.Class (MonadError (..)) import Control.Monad.IO.Class (MonadIO (liftIO))+import Control.Monad.Morph (MFunctor(hoist), MMonad(embed)) import Control.Monad.Reader (MonadReader (ask, local)) import Control.Monad.RWS.Class (MonadRWS) import Control.Monad.State.Lazy (MonadState (get, put)) import Control.Monad.Trans.Class (MonadTrans (lift)) import Control.Monad.Trans.Maybe (MaybeT (MaybeT)) import Control.Monad.Writer.Class (MonadWriter (listen, pass, tell, writer))+import Data.Either (Either(Left, Right), either)+import Data.Eq (Eq((==)))+import Data.Foldable (Foldable(foldr))+import Data.Function (($), const, flip)+import Data.Functor (Functor(fmap), (<$>)) import Data.Functor.Alt (Alt, (<!>)) import Data.Functor.Apply (Apply, liftF2, (<.>)) import Data.Functor.Bind (Bind, (>>-))-# if MIN_VERSION_base(4,9,0)+# if MIN_VERSION_transformers(0,5,0) import Data.Functor.Classes (Eq1, Ord1, Show1, compare1, eq1, liftCompare, liftEq, liftShowList, liftShowsPrec, showsPrec1,@@ -53,12 +58,19 @@ # endif import Data.Functor.Extend (Extend, duplicated) import Data.Functor.Identity (Identity (Identity))-import Data.Maybe (fromMaybe)+import Data.Int (Int)+import Data.Maybe (Maybe(Just, Nothing), fromMaybe)+import Data.Ord (Ord(compare)) import Data.Semigroup (Semigroup, (<>)) import Data.Semigroup.Foldable (Foldable1)+import Data.Traversable (Traversable(traverse))+import Data.Tuple (uncurry)+import Prelude (Show(showsPrec)) import System.Exit (ExitCode (ExitFailure, ExitSuccess)) --- hide the constructor, `Left 0` is an invalid state+-- | An exit code status where failing with a value `0` cannot be represented.+--+-- Transformer for either a non-zero exit code (`Int`) or a value :: `a`. data ExitcodeT f a = ExitcodeT (f (Either Int a)) @@ -71,6 +83,7 @@ type Exitcode0 = Exitcode () +-- | Construct a succeeding exit code with the given value. exitsuccess :: Applicative f => a@@ -78,12 +91,16 @@ exitsuccess = ExitcodeT . pure . Right +-- | Construct a succeeding exit code with unit. exitsuccess0 :: Applicative f => ExitcodeT0 f exitsuccess0 = exitsuccess () +-- | Construct a failing exit code with the given status.+--+-- If the given status is `0` then the exit code will succeed with unit. exitfailure0 :: Applicative f => Int@@ -144,11 +161,11 @@ _ExitSuccess :: Prism'- Exitcode0- ()+ (Exitcode a)+ a _ExitSuccess = prism'- (\() -> exitsuccess0)+ exitsuccess (\(ExitcodeT (Identity x)) -> x ^? _Right) instance Functor f => Functor (ExitcodeT f) where@@ -193,7 +210,7 @@ a `eq1` b instance Eq1 f => Eq1 (ExitcodeT f) where-# if MIN_VERSION_base(4,9,0)+# if MIN_VERSION_transformers(0,5,0) liftEq f (ExitcodeT a) (ExitcodeT b) = liftEq (liftEq f) a b # else@@ -206,7 +223,7 @@ a `compare1` b instance (Ord1 f) => Ord1 (ExitcodeT f) where-# if MIN_VERSION_base(4,9,0)+# if MIN_VERSION_transformers(0,5,0) liftCompare f (ExitcodeT a) (ExitcodeT b) = liftCompare (liftCompare f) a b # else@@ -216,14 +233,14 @@ instance (Show1 f, Show a) => Show (ExitcodeT f a) where showsPrec d (ExitcodeT m) =-# if MIN_VERSION_base(4,9,0)+# if MIN_VERSION_transformers(0,5,0) showsUnaryWith showsPrec1 "ExitcodeT" d m # else showsUnary1 "ExitcodeT" d m # endif instance Show1 f => Show1 (ExitcodeT f) where-# if MIN_VERSION_base(4,9,0)+# if MIN_VERSION_transformers(0,5,0) liftShowsPrec sp sl d (ExitcodeT fa) = let showsPrecF = liftA2 liftShowsPrec (uncurry liftShowsPrec) (uncurry liftShowList) (sp, sl) in showsUnaryWith showsPrecF "ExitcodeT" d fa@@ -286,3 +303,14 @@ liftCallCC callCC' f = ExitcodeT . callCC' $ \c -> runExitcode (f (\a -> ExitcodeT (c (Right a))))++instance MFunctor ExitcodeT where+ hoist nat (ExitcodeT x) =+ ExitcodeT (nat x)++instance MMonad ExitcodeT where+ embed nat (ExitcodeT x) = + let ex (Left e) = Left e+ ex (Right (Left e)) = Left e+ ex (Right (Right a)) = Right a+ in ExitcodeT (fmap ex (let ExitcodeT y = nat x in y))
test/Tests.hs view
@@ -4,12 +4,17 @@ import Data.Functor.Identity (Identity (..), runIdentity) import Data.Monoid ((<>)) -import Test.QuickCheck (Arbitrary (..), suchThat)+import Hedgehog (forAll, property, (===))+import qualified Hedgehog.Gen as Gen+import Hedgehog.Internal.Gen (MonadGen)+import qualified Hedgehog.Range as Range+import Test.QuickCheck (Arbitrary) import Test.QuickCheck.Checkers (EqProp (..), Test, TestBatch, eq) import Test.QuickCheck.Classes (applicative, functor) import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.Hedgehog (testProperty) import Test.Tasty.HUnit (testCase, (@?=))-import Test.Tasty.QuickCheck (testProperty)+import qualified Test.Tasty.QuickCheck as TQC import Control.Exitcode (Exitcode, ExitcodeT, exitCode, exitfailure0, exitsuccess,@@ -21,7 +26,7 @@ newtype EW f a = EW { unEW :: ExitcodeT f a } deriving (Eq, Show) instance (Applicative f, Arbitrary a) => Arbitrary (EW f a) where- arbitrary = fmap (EW . pure) arbitrary+ arbitrary = fmap (EW . pure) TQC.arbitrary instance Functor f => Functor (EW f) where fmap f = EW . fmap f . unEW@@ -35,10 +40,10 @@ type CheckMe = EW [] (Integer, Integer, Integer) -newtype NonZero = NonZero Int deriving Show--instance Arbitrary NonZero where- arbitrary = NonZero <$> suchThat arbitrary (/= 0)+nonZero :: MonadGen m => m Int+nonZero =+ let allOfTheInts = Range.linear (minBound :: Int) (maxBound :: Int)+ in Gen.filter (/= 0) (Gen.int allOfTheInts) main :: IO () main = defaultMain test_Exitcode@@ -65,12 +70,12 @@ exitFailurePrismTest :: TestTree exitFailurePrismTest = testGroup "_ExitFailure Prism" [- testProperty "review non-zero input" $- \(NonZero n) -> review _ExitFailure n == exitfailure0 n+ testProperty "review non-zero input" . property $+ forAll nonZero >>= (\n -> review _ExitFailure n === exitfailure0 n) , testCase "review 0" $ review _ExitFailure 0 @?= exitsuccess0- , testProperty "view non-zero input" $- \(NonZero n) -> exitfailure0 n ^? _ExitFailure == Just n+ , testProperty "view non-zero input" . property $+ forAll nonZero >>= (\n -> exitfailure0 n ^? _ExitFailure === Just n) , testCase "view 0" $ exitfailure0 0 ^? _ExitFailure @?= Nothing ]@@ -82,8 +87,8 @@ review _ExitSuccess () @?= exitsuccess0 , testCase "view exitsuccess0" $ exitsuccess0 ^? _ExitSuccess @?= Just ()- , testProperty "view exitfailure0 non-zero" $- \(NonZero n) -> exitfailure0 n ^? _ExitSuccess == Nothing+ , testProperty "view exitfailure0 non-zero" . property $+ forAll nonZero >>= (\n -> exitfailure0 n ^? _ExitSuccess === Nothing) , testCase "view exitfailure0 0" $ exitfailure0 0 ^? _ExitSuccess @?= Just () ]@@ -91,8 +96,8 @@ exitfailure0Test :: TestTree exitfailure0Test = testGroup "exitfailure0" [- testProperty "non-zero input" $- \(NonZero n) -> (runIdentity . runExitcode) (exitfailure0 n) == Left n+ testProperty "non-zero input" . property $+ forAll nonZero >>= (\n -> (runIdentity . runExitcode) (exitfailure0 n) === Left n) , testCase "0" $ (runIdentity . runExitcode) (exitfailure0 0) @?= Right () ]@@ -100,14 +105,14 @@ exitCodePrismTest :: TestTree exitCodePrismTest = testGroup "exitCode Prism" [- testProperty "`exitfailure0 n`, where n is non-zero" $- \(NonZero n) -> (review exitCode (exitfailure0 n)) == Identity (ExitFailure n)+ testProperty "`exitfailure0 n`, where n is non-zero" . property $+ forAll nonZero >>= \n -> (review exitCode (exitfailure0 n)) === Identity (ExitFailure n) , testCase "review `exitfailure 0`" $ runIdentity (review exitCode (exitfailure0 0)) @?= ExitSuccess , testCase "review `exitsuccess0`" $ runIdentity (review exitCode exitsuccess0) @?= ExitSuccess- , testProperty "view ExitFailure n, where n is non-zero" $- \(NonZero n) -> Identity (ExitFailure n) ^? exitCode == Just (exitfailure0 n)+ , testProperty "view ExitFailure n, where n is non-zero" . property $+ forAll nonZero >>= (\n -> Identity (ExitFailure n) ^? exitCode === Just (exitfailure0 n)) , testCase "view ExitFailure 0" $ runExitcode (Identity (ExitFailure 0) ^. exitCode) @?= (MaybeT (Identity Nothing)) , testCase "view ExitSuccess" $@@ -120,4 +125,4 @@ tastyCheckersProperty :: Test -> TestTree tastyCheckersProperty =- uncurry testProperty+ uncurry TQC.testProperty