module Test.QuickCheck.DynamicLogic.SmartShrinking (shrinkSmart) where

import Test.QuickCheck

-- | This combinator captures the 'smart shrinking' implemented for the
-- Smart type wrapper in Test.QuickCheck.Modifiers.
shrinkSmart :: (a -> [a]) -> Smart a -> [Smart a]
shrinkSmart :: (a -> [a]) -> Smart a -> [Smart a]
shrinkSmart a -> [a]
shr (Smart Int
i a
x) = Int -> [Smart a] -> [Smart a]
forall a. Int -> [a] -> [a]
take Int
i' [Smart a]
ys [Smart a] -> [Smart a] -> [Smart a]
forall a. [a] -> [a] -> [a]
`ilv` Int -> [Smart a] -> [Smart a]
forall a. Int -> [a] -> [a]
drop Int
i' [Smart a]
ys
 where
  ys :: [Smart a]
ys = [Int -> a -> Smart a
forall a. Int -> a -> Smart a
Smart Int
j a
y | (Int
j, a
y) <- [Int
0 ..] [Int] -> [a] -> [(Int, a)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` a -> [a]
shr a
x]
  i' :: Int
i' = Int
0 Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2)
  [] ilv :: [a] -> [a] -> [a]
`ilv` [a]
bs = [a]
bs
  [a]
as `ilv` [] = [a]
as
  (a
a : [a]
as) `ilv` (a
b : [a]
bs) = a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
b a -> [a] -> [a]
forall a. a -> [a] -> [a]
: ([a]
as [a] -> [a] -> [a]
`ilv` [a]
bs)