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
iInt -> 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)