packages feed

sequence-0.9.9.0: test/Queue.hs

{-# language BangPatterns #-}
{-# options_ghc -fno-warn-orphans #-}

module Queue where
import Data.Sequence.Queue.Internal
import Test.QuickCheck
import Valid

{-
data P a = a :* a
  deriving (Functor, Foldable, Traversable)

data B a where
  B1 :: a    -> B a
  B2 :: !(P a)  -> B a

data Queue a  where
  Q0 :: Queue a
  Q1 :: a  -> Queue a
  QN :: !(B a) -> Queue (P a) -> !(B a) -> Queue a
  -}


instance Valid Queue where
  -- Just force the structure to make sure it's finite
  -- and fully defined.
  valid = property . foldr (\_ r -> r) True

instance Arbitrary a => Arbitrary (Queue a) where
  arbitrary = liftArbitrary arbitrary

instance Arbitrary1 Queue where
  liftArbitrary el = sized $ \s -> do
    len <- chooseInt (0, s)
    mkArbQ len el

-- Generate an arbitrary queue of exactly the given size.
mkArbQ :: Int -> Gen a -> Gen (Queue a)
mkArbQ 0 _ = pure Q0
mkArbQ 1 g = Q1 <$> g
mkArbQ 2 g = QN <$> mkArbB 1 g <*> pure Q0 <*> mkArbB 1 g
mkArbQ 3 g = oneof
  [ QN <$> mkArbB 1 g <*> pure Q0 <*> mkArbB 2 g
  , QN <$> mkArbB 2 g <*> pure Q0 <*> mkArbB 1 g ]
mkArbQ n g
  | even n
  = oneof
      [ QN <$> mkArbB 2 g <*> mkArbQ ((n - 4) `quot` 2) (mkArbP g) <*> mkArbB 2 g
      , QN <$> mkArbB 1 g <*> mkArbQ ((n - 2) `quot` 2) (mkArbP g) <*> mkArbB 1 g ]
  | otherwise
  = oneof
      [ QN <$> mkArbB 2 g <*> mkArbQ ((n - 3) `quot` 2) (mkArbP g) <*> mkArbB 1 g
      , QN <$> mkArbB 1 g <*> mkArbQ ((n - 3) `quot` 2) (mkArbP g) <*> mkArbB 2 g ]

mkArbB :: Int -> Gen a -> Gen (B a)
mkArbB 1 g = B1 <$> g
mkArbB 2 g = B2 <$> mkArbP g
mkArbB _ _ = error "mkArbB must be called with 1 or 2."

mkArbP :: Gen a -> Gen (P a)
mkArbP g = (:*) <$> g <*> g