abides (empty) → 0.0.0
raw patch · 21 files changed
+444/−0 lines, 21 filesdep +abidesdep +basedep +comonadsetup-changed
Dependencies added: abides, base, comonad, tasty, tasty-quickcheck
Files
- ChangeLog.md +3/−0
- LICENSE +30/−0
- README.md +7/−0
- Setup.hs +2/−0
- abides.cabal +70/−0
- src/Test/Abides.hs +2/−0
- src/Test/Abides/Control/Alternative.hs +13/−0
- src/Test/Abides/Control/Applicative.hs +28/−0
- src/Test/Abides/Control/Category.hs +14/−0
- src/Test/Abides/Control/Comonad.hs +15/−0
- src/Test/Abides/Control/Monad.hs +24/−0
- src/Test/Abides/Data/Bounded.hs +5/−0
- src/Test/Abides/Data/Enum.hs +16/−0
- src/Test/Abides/Data/Eq.hs +23/−0
- src/Test/Abides/Data/Foldable.hs +8/−0
- src/Test/Abides/Data/Functor.hs +10/−0
- src/Test/Abides/Data/Monoid.hs +11/−0
- src/Test/Abides/Data/Ord.hs +16/−0
- src/Test/Abides/Data/Semigroup.hs +7/−0
- src/Test/Abides/Properties.hs +31/−0
- test/Spec.hs +109/−0
+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for abides++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Athan Clark (c) 2019++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 Author name here 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.
+ README.md view
@@ -0,0 +1,7 @@+# abides++++++Just a bunch of functions that make sure a class abides by its laws, man.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ abides.cabal view
@@ -0,0 +1,70 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: f1fefe867335372cccdb4d04ab5a2e0285abcc0e8080fbce2e12adf70dc571bd++name: abides+version: 0.0.0+synopsis: Simple boolean tests to see if a value abides by certain properties+description: Please see the README on GitHub at <https://github.com/athanclark/abides#readme>+category: Data, Testing+homepage: https://github.com/athanclark/abides#readme+bug-reports: https://github.com/athanclark/abides/issues+author: Athan Clark+maintainer: athan.clark@gmail.com+copyright: 2019 Athan Clark+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md++source-repository head+ type: git+ location: https://github.com/athanclark/abides++library+ exposed-modules:+ Test.Abides+ Test.Abides.Control.Alternative+ Test.Abides.Control.Applicative+ Test.Abides.Control.Category+ Test.Abides.Control.Comonad+ Test.Abides.Control.Monad+ Test.Abides.Data.Bounded+ Test.Abides.Data.Enum+ Test.Abides.Data.Eq+ Test.Abides.Data.Foldable+ Test.Abides.Data.Functor+ Test.Abides.Data.Monoid+ Test.Abides.Data.Ord+ Test.Abides.Data.Semigroup+ Test.Abides.Properties+ other-modules:+ Paths_abides+ hs-source-dirs:+ src+ build-depends:+ base >=4.7 && <5+ , comonad+ default-language: Haskell2010++test-suite abides-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Paths_abides+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ abides+ , base >=4.7 && <5+ , comonad+ , tasty+ , tasty-quickcheck+ default-language: Haskell2010
+ src/Test/Abides.hs view
@@ -0,0 +1,2 @@+module Test.Abides where+
+ src/Test/Abides/Control/Alternative.hs view
@@ -0,0 +1,13 @@+module Test.Abides.Control.Alternative where++import Control.Applicative (Alternative ((<|>)), empty)+++-- | (f <|> g) <*> x == (f <*> x) <|> (g <|> x)+distributive :: Alternative f => Applicative f => Eq (f b) => f (a -> b) -> f (a -> b) -> f a -> Bool+distributive f g x = ((f <|> g) <*> x) == ((f <*> x) <|> (g <*> x))+++-- | empty <*> x == empty+annihilation :: Alternative f => Applicative f => Eq (f b) => f (a -> b) -> Bool+annihilation f = (f <*> empty) == empty
+ src/Test/Abides/Control/Applicative.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE+ RankNTypes+ , ScopedTypeVariables+ #-}++module Test.Abides.Control.Applicative where+++identity :: Applicative f => Eq (f a) => f a -> Bool+identity x = (pure id <*> x) == x+++composition :: Applicative f => Eq (f c) => f (b -> c) -> f (a -> b) -> f a -> Bool+composition f g h = (pure (.) <*> f <*> g <*> h) == (f <*> (g <*> h))+++-- FIXME ambiguous type?+-- homomorphism :: forall f a b. Applicative f => Eq (f b) => (a -> b) -> a -> Bool+-- homomorphism f x = (f' <*> x') == y'+-- where+-- f' :: f (a -> b)+-- f' = pure f++-- x' :: f a+-- x' = pure x++-- y' :: f b+-- y' = pure (f x)
+ src/Test/Abides/Control/Category.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE NoImplicitPrelude #-}++module Test.Abides.Control.Category where++import Prelude hiding ((.), id)+import Control.Category (Category ((.), id))+++identity :: Category c => Eq (c a b) => c a b -> Bool+identity p = ((id . p) == p) && ((p . id) == p)+++associative :: Category q => Eq (q a d) => q c d -> q b c -> q a b -> Bool+associative x y z = (x . (y . z)) == ((x . y) . z)
+ src/Test/Abides/Control/Comonad.hs view
@@ -0,0 +1,15 @@+module Test.Abides.Control.Comonad where++import Control.Comonad (Comonad (extend, extract), (<<=))+++leftIdentity :: Comonad w => Eq (w a) => w a -> Bool+leftIdentity x = (extract <<= x) == x+++rightIdentity :: Comonad w => Eq a => (w a -> a) -> w a -> Bool+rightIdentity f x = extract (f <<= x) == f x+++associative :: Comonad w => Eq (w c) => (w b -> c) -> (w a -> b) -> w a -> Bool+associative f g x = extend f (extend g x) == extend (f . extend g) x
+ src/Test/Abides/Control/Monad.hs view
@@ -0,0 +1,24 @@+module Test.Abides.Control.Monad where+++import Control.Monad (MonadPlus (mzero, mplus))+++leftIdentity :: Monad m => Eq (m b) => (a -> m b) -> a -> Bool+leftIdentity f x = (pure x >>= f) == f x+++rightIdentity :: Monad m => Eq (m a) => m a -> Bool+rightIdentity x = (x >>= pure) == x+++associative :: Monad m => Eq (m c) => (a -> m b) -> (b -> m c) -> m a -> Bool+associative f g x = ((x >>= f) >>= g) == (x >>= (\k -> f k >>= g))+++annihilation :: MonadPlus m => Eq (m b) => (a -> m b) -> Bool+annihilation f = (mzero >>= f) == mzero+++distributive :: MonadPlus m => Eq (m b) => (a -> m b) -> m a -> m a -> Bool+distributive f x y = (mplus x y >>= f) == mplus (x >>= f) (y >>= f)
+ src/Test/Abides/Data/Bounded.hs view
@@ -0,0 +1,5 @@+module Test.Abides.Data.Bounded where++-- | minBound <= x <= maxBound?+bounded :: Bounded a => Ord a => a -> Bool+bounded x = minBound <= x && x <= maxBound
+ src/Test/Abides/Data/Enum.hs view
@@ -0,0 +1,16 @@+module Test.Abides.Data.Enum where+++-- | compare x y == compare (fromEnum x) (fromEnum y)+compareHom :: Enum a => Ord a => a -> a -> Bool+compareHom x y = compare x y == compare (fromEnum x) (fromEnum y)+++-- | pred (succ x) == x+predsucc :: Enum a => Eq a => a -> Bool+predsucc x = pred (succ x) == x+++-- | succ (pred x) == x+succpred :: Enum a => Eq a => a -> Bool+succpred x = succ (pred x) == x
+ src/Test/Abides/Data/Eq.hs view
@@ -0,0 +1,23 @@+module Test.Abides.Data.Eq+ ( P.reflexive+ , symmetry+ , transitive+ , negation+ ) where++import qualified Test.Abides.Properties as P+++-- | x == y => y == x?+symmetry :: Eq a => a -> a -> Bool+symmetry x y = if x == y then y == x else True+++-- | x == y && y == z => x == z+transitive :: Eq a => a -> a -> a -> Bool+transitive x y z = if x == y && y == z then x == z else True+++-- | x /= y => not (x == y)+negation :: Eq a => a -> a -> Bool+negation x y = if x /= y then not (x == y) else True
+ src/Test/Abides/Data/Foldable.hs view
@@ -0,0 +1,8 @@+module Test.Abides.Data.Foldable where++import Data.Foldable (fold)+++-- | fold (map f x) == foldMap f x+foldMap' :: Foldable f => Functor f => Monoid b => Eq b => (a -> b) -> f a -> Bool+foldMap' f x = fold (fmap f x) == foldMap f x
+ src/Test/Abides/Data/Functor.hs view
@@ -0,0 +1,10 @@+module Test.Abides.Data.Functor where+++-- | fmap id x == x?+identity :: Functor f => Eq (f a) => f a -> Bool+identity x = fmap id x == x++-- | fmap (f . g) x == fmap f (fmap g x)?+composition :: Functor f => Eq (f a) => (a -> a) -> (a -> a) -> f a -> Bool+composition f g x = fmap (f . g) x == fmap f (fmap g x)
+ src/Test/Abides/Data/Monoid.hs view
@@ -0,0 +1,11 @@+module Test.Abides.Data.Monoid where++import Test.Abides.Properties (constL, constR)+++leftIdentity :: Monoid a => Eq a => a -> Bool+leftIdentity = constR (<>) mempty+++rightIdentity :: Monoid a => Eq a => a -> Bool+rightIdentity x = constL (<>) x mempty
+ src/Test/Abides/Data/Ord.hs view
@@ -0,0 +1,16 @@+module Test.Abides.Data.Ord where+++-- | x <= x?+reflexive :: Ord a => a -> Bool+reflexive x = x <= x+++-- | x <= y && y <= x => x == y+antisymmetry :: Ord a => a -> a -> Bool+antisymmetry x y = if x <= y && y <= x then x == y else True+++-- | x <= y && y <= z => x <= z+transitive :: Ord a => a -> a -> a -> Bool+transitive x y z = if x <= y && y <= z then x <= z else True
+ src/Test/Abides/Data/Semigroup.hs view
@@ -0,0 +1,7 @@+module Test.Abides.Data.Semigroup where++import qualified Test.Abides.Properties as P+++associative :: Semigroup a => Eq a => a -> a -> a -> Bool+associative = P.associative (<>)
+ src/Test/Abides/Properties.hs view
@@ -0,0 +1,31 @@+module Test.Abides.Properties where+++-- | x == x?+reflexive :: Eq a => a -> Bool+reflexive x = x == x++-- | f x y == f y x?+commutative :: Eq b => (a -> a -> b) -> a -> a -> Bool+commutative f x y = f x y == f y x++-- | f (f x y) z == f x (f y z)?+associative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool+associative f x y z = f (f x y) z == f x (f y z)++-- | f (f x) == f x?+idempotent :: Eq a => (a -> a) -> a -> Bool+idempotent f x = f (f x) == f x++-- | f (g x y) == g (f x) (f y)?+distributive :: Eq a => (a -> a) -> (a -> a -> a) -> a -> a -> Bool+distributive f g x y = f (g x y) == g (f x) (f y)++-- | f x y == x? Note: bottom ~ forall y. f bottom y == bottom, while unit ~ forall x. f x unit == x+constL :: Eq a => (a -> a -> a) -> a -> a -> Bool+constL f x y = f x y == x++-- | f x y == y?+constR :: Eq a => (a -> a -> a) -> a -> a -> Bool+constR f x y = f x y == y+
+ test/Spec.hs view
@@ -0,0 +1,109 @@+import qualified Test.Abides.Control.Alternative as Alt+import qualified Test.Abides.Control.Applicative as App+import qualified Test.Abides.Control.Category as Cat+import qualified Test.Abides.Control.Comonad as Com+import qualified Test.Abides.Control.Monad as Mon+import qualified Test.Abides.Data.Bounded as Bou+import qualified Test.Abides.Data.Enum as Enu+import qualified Test.Abides.Data.Eq as Eq+import qualified Test.Abides.Data.Foldable as Fol+import qualified Test.Abides.Data.Functor as Fun+import qualified Test.Abides.Data.Monoid as Mono+import qualified Test.Abides.Data.Ord as Ord+import qualified Test.Abides.Data.Semigroup as Sem++import Test.Tasty (defaultMain, testGroup)+import Test.Tasty.QuickCheck (testProperty)++import Data.Monoid (Sum (..))++++main :: IO ()+main = defaultMain $ testGroup "All Tests"+ [ testGroup "Test.Abides.Control"+ [ testProperty "Alternative" alternativeTests+ , testProperty "Applicative" applicativeTests+ -- , testProperty "Category" categoryTests+ , testProperty "Comonad" comonadTests+ , testProperty "Monad" monadTests+ , testProperty "MonadPlus" monadPlusTests+ ]+ , testGroup "Test.Abides.Data"+ [ testProperty "Bounded" boundedTests+ , testProperty "Enum" enumTests+ , testProperty "Eq" eqTests+ , testProperty "Foldable" foldableTests+ , testProperty "Functor" functorTests+ , testProperty "Monoid" monoidTests+ , testProperty "Ord" ordTests+ , testProperty "Semigroup" semigroupTests+ ]+ ]+ where+ alternativeTests :: [Int] -> Bool+ alternativeTests x = and+ [ Alt.distributive [(+ 1)] [(* 2)] x+ , Alt.annihilation (map (+) x)+ ]+ applicativeTests :: [Int] -> Bool+ applicativeTests x = and+ [ App.identity x+ , App.composition [(+ 1)] [(* 2)] x+ ]+ -- categoryTests :: Kleisli [] Int Int -> Bool+ -- categoryTests x = and+ -- [ Cat.identity x+ -- , App.composition [(+ 1)] [(* 2)] x+ -- ]+ comonadTests :: (Int,Int) -> Bool+ comonadTests x = and+ [ Com.leftIdentity x+ , Com.rightIdentity (\(a,b) -> b + 1) x+ , Com.associative (\(a,b) -> b * 2) (\(a,b) -> b + 1) x+ ]+ monadTests :: [Int] -> Bool+ monadTests x = and+ [ Mon.leftIdentity (\a -> [a] ++ x) 5+ , Mon.rightIdentity x+ , Mon.associative (\a -> [a,1]) (\a -> [2,a]) x+ ]+ monadPlusTests :: Maybe Int -> Bool+ monadPlusTests x = and+ [ Mon.annihilation (\a -> Just (a + 1))+ , Mon.distributive (\a -> Just (a + 1)) x (Just 5)+ ]+ boundedTests :: Int -> Bool+ boundedTests x = Bou.bounded x+ enumTests :: Int -> Bool+ enumTests x = and+ [ Enu.compareHom x 1+ , Enu.predsucc x+ , Enu.succpred x+ ]+ eqTests :: (Int,Int) -> Bool+ eqTests (x,y) = and+ [ Eq.symmetry x y+ , Eq.transitive x y x+ , Eq.negation x y+ ]+ foldableTests :: [Sum Int] -> Bool+ foldableTests x = Fol.foldMap' (+ (Sum 5)) x+ functorTests :: [Int] -> Bool+ functorTests x = and+ [ Fun.identity x+ , Fun.composition (+ 5) (* 2) x+ ]+ monoidTests :: Sum Int -> Bool+ monoidTests x = and+ [ Mono.leftIdentity x+ , Mono.rightIdentity x+ ]+ ordTests :: (Int,Int) -> Bool+ ordTests (x,y) = and+ [ Ord.reflexive x+ , Ord.antisymmetry x y+ , Ord.transitive x y x+ ]+ semigroupTests :: (Sum Int, Sum Int, Sum Int) -> Bool+ semigroupTests (x,y,z) = Sem.associative x y z