module Test.Memory.Laws ( semigroupLaw , monoidIdentityLaw , showReadLaw ) where import Data.Semigroup (Semigroup (..)) import Hedgehog (MonadGen, Property, forAll, property, (===)) import Numeric.Natural (Natural) import Membrain.Memory (AnyMemory (..), Memory (..), readMemory, showMemory) import qualified Membrain.Units as Mem import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range ---------------------------------------------------------------------------- -- Laws ---------------------------------------------------------------------------- {- | The semigroup associativity axiom: @ x <> (y <> z) ≡ (x <> y) <> z @ -} semigroupLaw :: Property semigroupLaw = property $ do x <- forAll genBitMemory y <- forAll genBitMemory z <- forAll genBitMemory (x <> y) <> z === x <> (y <> z) {- | Identity law for Monoid @ mempty <> x = x x <> mempty = x @ -} monoidIdentityLaw :: Property monoidIdentityLaw = property $ do x <- forAll genBitMemory x <> mempty === x mempty <> x === x showReadLaw :: Property showReadLaw = property $ do MkAnyMemory mem <- forAll genAnyMemory readMemory (showMemory mem) === Just mem ---------------------------------------------------------------------------- -- Generators ---------------------------------------------------------------------------- -- | Generates random natural number up to 10^20. genNatural :: (MonadGen m) => m Natural genNatural = Gen.integral (Range.constant 0 $ 10 ^ (20 :: Int)) genBitMemory :: MonadGen m => m (Memory Mem.Bit) genBitMemory = Memory <$> genNatural genAnyMemory :: MonadGen m => m AnyMemory genAnyMemory = genNatural >>= unitChooser -- | Returns random 'AnyMemory'. unitChooser :: (MonadGen m) => Natural -> m AnyMemory unitChooser n = Gen.element [ MkAnyMemory (Memory @Mem.Bit n) , MkAnyMemory (Memory @Mem.Nibble n) , MkAnyMemory (Memory @Mem.Byte n) , MkAnyMemory (Memory @Mem.Kilobyte n) , MkAnyMemory (Memory @Mem.Megabyte n) , MkAnyMemory (Memory @Mem.Gigabyte n) , MkAnyMemory (Memory @Mem.Terabyte n) , MkAnyMemory (Memory @Mem.Petabyte n) , MkAnyMemory (Memory @Mem.Exabyte n) , MkAnyMemory (Memory @Mem.Zettabyte n) , MkAnyMemory (Memory @Mem.Yottabyte n) , MkAnyMemory (Memory @Mem.Kibibyte n) , MkAnyMemory (Memory @Mem.Mebibyte n) , MkAnyMemory (Memory @Mem.Gibibyte n) , MkAnyMemory (Memory @Mem.Tebibyte n) , MkAnyMemory (Memory @Mem.Pebibyte n) , MkAnyMemory (Memory @Mem.Exbibyte n) , MkAnyMemory (Memory @Mem.Zebibyte n) , MkAnyMemory (Memory @Mem.Yobibyte n) ]