{-
We could add checks for overflows
by checking whether the most significant bit of every part is zero.
-}
module Combinatorics.Battleship.Fleet (
   -- * basics
   T,
   ShipSize,
   NumberOfShips,

   cumulate,
   dec, inc,
   empty,
   fromList, toList,
   fromSizes, toSizes,
   lookup,
   maxSize,
   singleton,
   subset,

   -- * configurations for some established versions
   german,
   english,

   -- * tests
   propList,
   propSizes,
   propCumulate,
   propSubset,

   propInc,
   propDec,
   propIncDec,
   ) where

import qualified Foreign.Storable.Newtype as Store
import Foreign.Storable (Storable, sizeOf, alignment, poke, peek, )

import Data.Foldable (foldMap, )
import Data.Bool.HT (if', )

import Data.Monoid (Monoid, mempty, mappend, )
import Data.Semigroup (Semigroup, (<>), )
import Data.Bits ((.&.), (.|.), xor, shiftL, shiftR, )
import Data.Word (Word32, )

import Prelude hiding (lookup)

import qualified Test.QuickCheck as QC


type ShipSize = Int
type NumberOfShips = Int

{- |
Efficient representation of a (Map ShipSize NumberOfShips).

This is known as SIMD within a register <https://en.wikipedia.org/wiki/SWAR>.
-}
newtype T = Cons {T -> Word32
decons :: Word32}
   deriving (T -> T -> Bool
(T -> T -> Bool) -> (T -> T -> Bool) -> Eq T
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: T -> T -> Bool
$c/= :: T -> T -> Bool
== :: T -> T -> Bool
$c== :: T -> T -> Bool
Eq, Eq T
Eq T
-> (T -> T -> Ordering)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> T)
-> (T -> T -> T)
-> Ord T
T -> T -> Bool
T -> T -> Ordering
T -> T -> T
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: T -> T -> T
$cmin :: T -> T -> T
max :: T -> T -> T
$cmax :: T -> T -> T
>= :: T -> T -> Bool
$c>= :: T -> T -> Bool
> :: T -> T -> Bool
$c> :: T -> T -> Bool
<= :: T -> T -> Bool
$c<= :: T -> T -> Bool
< :: T -> T -> Bool
$c< :: T -> T -> Bool
compare :: T -> T -> Ordering
$ccompare :: T -> T -> Ordering
$cp1Ord :: Eq T
Ord) -- for use as key in a Map


instance Show T where
   showsPrec :: Int -> T -> ShowS
showsPrec Int
prec T
x =
      Bool -> ShowS -> ShowS
showParen (Int
precInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
         String -> ShowS
showString String
"Fleet.fromList " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
         [(Int, Int)] -> ShowS
forall a. Show a => a -> ShowS
shows (T -> [(Int, Int)]
toList T
x)

instance Semigroup T where
   Cons Word32
x <> :: T -> T -> T
<> Cons Word32
y = Word32 -> T
Cons (Word32
xWord32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+Word32
y)

instance Monoid T where
   mempty :: T
mempty = Word32 -> T
Cons Word32
0
   mappend :: T -> T -> T
mappend = T -> T -> T
forall a. Semigroup a => a -> a -> a
(<>)

instance Storable T where
   sizeOf :: T -> Int
sizeOf = (T -> Word32) -> T -> Int
forall core wrapper.
Storable core =>
(wrapper -> core) -> wrapper -> Int
Store.sizeOf T -> Word32
decons
   alignment :: T -> Int
alignment = (T -> Word32) -> T -> Int
forall core wrapper.
Storable core =>
(wrapper -> core) -> wrapper -> Int
Store.alignment T -> Word32
decons
   poke :: Ptr T -> T -> IO ()
poke = (T -> Word32) -> Ptr T -> T -> IO ()
forall core wrapper.
Storable core =>
(wrapper -> core) -> Ptr wrapper -> wrapper -> IO ()
Store.poke T -> Word32
decons
   peek :: Ptr T -> IO T
peek = (Word32 -> T) -> Ptr T -> IO T
forall core wrapper.
Storable core =>
(core -> wrapper) -> Ptr wrapper -> IO wrapper
Store.peek Word32 -> T
Cons


debug :: Bool
debug :: Bool
debug = Bool
False

{-# INLINE checkSize #-}
checkSize :: String -> ShipSize -> a -> a
checkSize :: String -> Int -> a -> a
checkSize String
name Int
size =
   Bool -> a -> a -> a
forall a. Bool -> a -> a -> a
if' (Bool
debug Bool -> Bool -> Bool
&& (Int
sizeInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
0 Bool -> Bool -> Bool
|| Int
maxSizeInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
size)) (a -> a -> a) -> a -> a -> a
forall a b. (a -> b) -> a -> b
$
      String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": ship size " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
size String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" out of range"

{-
The number of bits must be large enough
in order to also hold a cumulative fleet.
-}
bitsPerNumber :: Int
bitsPerNumber :: Int
bitsPerNumber = Int
4

digitMask :: Word32
digitMask :: Word32
digitMask = Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
1 Int
bitsPerNumber Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1

maxSize :: Int
maxSize :: Int
maxSize = Int
8

bitPosFromSize :: Int -> Int
bitPosFromSize :: Int -> Int
bitPosFromSize Int
size =
   (Int
sizeInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
bitsPerNumber

empty :: T
empty :: T
empty = T
forall a. Monoid a => a
mempty

singleton :: ShipSize -> NumberOfShips -> T
singleton :: Int -> Int -> T
singleton Int
size Int
n =
   String -> Int -> (Word32 -> T) -> Word32 -> T
forall a. String -> Int -> a -> a
checkSize String
"Fleet.singleton" Int
size
   Word32 -> T
Cons (Word32 -> T) -> Word32 -> T
forall a b. (a -> b) -> a -> b
$ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) (Int -> Int
bitPosFromSize Int
size)

fromList :: [(ShipSize, NumberOfShips)] -> T
fromList :: [(Int, Int)] -> T
fromList = ((Int, Int) -> T) -> [(Int, Int)] -> T
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ((Int -> Int -> T) -> (Int, Int) -> T
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> Int -> T
singleton)

fromSizes :: [ShipSize] -> T
fromSizes :: [Int] -> T
fromSizes = [(Int, Int)] -> T
fromList ([(Int, Int)] -> T) -> ([Int] -> [(Int, Int)]) -> [Int] -> T
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Int, Int)) -> [Int] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((Int -> Int -> (Int, Int)) -> Int -> Int -> (Int, Int)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (,) Int
1)


lookup :: T -> ShipSize -> NumberOfShips
lookup :: T -> Int -> Int
lookup (Cons Word32
bits) Int
size =
   String -> Int -> Int -> Int
forall a. String -> Int -> a -> a
checkSize String
"Fleet.lookup" Int
size (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$
   Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$
      Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
bits (Int -> Int
bitPosFromSize Int
size)
      Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&.
      Word32
digitMask

toList :: T -> [(ShipSize, NumberOfShips)]
toList :: T -> [(Int, Int)]
toList T
fleet =
   ((Int, Int) -> Bool) -> [(Int, Int)] -> [(Int, Int)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int
0Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/=) (Int -> Bool) -> ((Int, Int) -> Int) -> (Int, Int) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> Int
forall a b. (a, b) -> b
snd) ([(Int, Int)] -> [(Int, Int)]) -> [(Int, Int)] -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$
   (Int -> (Int, Int)) -> [Int] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
size -> (Int
size, T -> Int -> Int
lookup T
fleet Int
size)) [Int
1..Int
maxSize]

toSizes :: T -> [ShipSize]
toSizes :: T -> [Int]
toSizes = ((Int, Int) -> [Int]) -> [(Int, Int)] -> [Int]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Int
size,Int
n) -> Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
n Int
size) ([(Int, Int)] -> [Int]) -> (T -> [(Int, Int)]) -> T -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T -> [(Int, Int)]
toList


propList :: T -> Bool
propList :: T -> Bool
propList T
fleet  =  T
fleet T -> T -> Bool
forall a. Eq a => a -> a -> Bool
== [(Int, Int)] -> T
fromList (T -> [(Int, Int)]
toList T
fleet)

propSizes :: T -> Bool
propSizes :: T -> Bool
propSizes T
fleet  =  T
fleet T -> T -> Bool
forall a. Eq a => a -> a -> Bool
== [Int] -> T
fromSizes (T -> [Int]
toSizes T
fleet)


{- |
@lookup (cumulate fleet) size@
returns the number of all ships that are at least @size@ squares big.
-}
cumulate :: T -> T
cumulate :: T -> T
cumulate = T -> T
cumulateDiv

cumulateCascade :: T -> T
cumulateCascade :: T -> T
cumulateCascade (Cons Word32
x) =
   Word32 -> T
Cons (Word32 -> T) -> Word32 -> T
forall a b. (a -> b) -> a -> b
$ (Word32 -> Int -> Word32) -> Word32 -> [Int] -> Word32
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Word32
y Int
n -> Word32
y Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
y Int
n) Word32
x ([Int] -> Word32) -> [Int] -> Word32
forall a b. (a -> b) -> a -> b
$
   (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
maxSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
bitsPerNumber) ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Int -> Int) -> Int -> [Int]
forall a. (a -> a) -> a -> [a]
iterate (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*) Int
bitsPerNumber

{- |
The total number ships must be strictly smaller than 15.
-}
cumulateDiv :: T -> T
cumulateDiv :: T -> T
cumulateDiv (Cons Word32
x) =
   Word32 -> T
Cons (Word32 -> T) -> Word32 -> T
forall a b. (a -> b) -> a -> b
$
   case Word32 -> Word32 -> (Word32, Word32)
forall a. Integral a => a -> a -> (a, a)
divMod Word32
x Word32
digitMask of
      (Word32
q,Word32
r) -> Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
q Int
bitsPerNumber Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word32
r

genBounded :: QC.Gen T
genBounded :: Gen T
genBounded = do
   Int
n <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
QC.choose (Int
0, Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
digitMask Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
   ([Int] -> T) -> Gen [Int] -> Gen T
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Int] -> T
fromSizes (Gen [Int] -> Gen T) -> Gen [Int] -> Gen T
forall a b. (a -> b) -> a -> b
$ Int -> Gen Int -> Gen [Int]
forall a. Int -> Gen a -> Gen [a]
QC.vectorOf Int
n (Gen Int -> Gen [Int]) -> Gen Int -> Gen [Int]
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
QC.choose (Int
1, Int
maxSize)

propCumulate :: QC.Property
propCumulate :: Property
propCumulate =
   Gen T -> (T -> Bool) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen T
genBounded ((T -> Bool) -> Property) -> (T -> Bool) -> Property
forall a b. (a -> b) -> a -> b
$
      \T
x -> T -> T
cumulateCascade T
x T -> T -> Bool
forall a. Eq a => a -> a -> Bool
== T -> T
cumulateDiv T
x


{-# INLINE subset #-}
subset :: T -> T -> Bool
subset :: T -> T -> Bool
subset = T -> T -> Bool
subsetParity

subsetLookup :: T -> T -> Bool
subsetLookup :: T -> T -> Bool
subsetLookup T
x T
y =
   (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\Int
size -> T -> Int -> Int
lookup T
x Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= T -> Int -> Int
lookup T
y Int
size) [Int
1..Int
maxSize]

{- |
This implementation checks whether unwanted borrows occurred.
@x<=y@ is required for the largest ship size.
-}
subsetParity :: T -> T -> Bool
subsetParity :: T -> T -> Bool
subsetParity =
   let sizesPos :: Word32
sizesPos =
         Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
div (Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
1 (Int
maxSizeInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
bitsPerNumber) Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1) Word32
digitMask
   in  \(Cons Word32
x) (Cons Word32
y) ->
         Word32
xWord32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<=Word32
y  Bool -> Bool -> Bool
&&  Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
xor (Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
xor Word32
x Word32
y) (Word32
yWord32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
-Word32
x) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
sizesPos Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0

propSubset :: T -> T -> Bool
propSubset :: T -> T -> Bool
propSubset T
x T
y  =  T -> T -> Bool
subsetLookup T
x T
y Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== T -> T -> Bool
subsetParity T
x T
y


inc :: ShipSize -> T -> T
inc :: Int -> T -> T
inc Int
size (Cons Word32
fleet) =
   String -> Int -> T -> T
forall a. String -> Int -> a -> a
checkSize String
"Fleet.inc" Int
size (T -> T) -> T -> T
forall a b. (a -> b) -> a -> b
$
   Word32 -> T
Cons (Word32 -> T) -> Word32 -> T
forall a b. (a -> b) -> a -> b
$ Word32
fleet Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
1 (Int -> Int
bitPosFromSize Int
size)

dec :: ShipSize -> T -> T
dec :: Int -> T -> T
dec Int
size (Cons Word32
fleet) =
   String -> Int -> T -> T
forall a. String -> Int -> a -> a
checkSize String
"Fleet.inc" Int
size (T -> T) -> T -> T
forall a b. (a -> b) -> a -> b
$
   Word32 -> T
Cons (Word32 -> T) -> Word32 -> T
forall a b. (a -> b) -> a -> b
$ Word32
fleet Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
1 (Int -> Int
bitPosFromSize Int
size)


{- |
The main configuration given
in <https://de.wikipedia.org/wiki/Schiffe_versenken>.
-}
german :: T
german :: T
german = [(Int, Int)] -> T
fromList [(Int
5,Int
1), (Int
4,Int
2), (Int
3,Int
3), (Int
2,Int
4)]

{- |
The main configuration given
in <https://en.wikipedia.org/wiki/Battleship_(game)>.
-}
english :: T
english :: T
english = [(Int, Int)] -> T
fromList [(Int
2,Int
1), (Int
3,Int
2), (Int
4,Int
1), (Int
5,Int
1)]


genShipSize :: QC.Gen ShipSize
genShipSize :: Gen Int
genShipSize = (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
QC.choose (Int
1, Int
maxSize)

propInc :: T -> QC.Property
propInc :: T -> Property
propInc T
fleet =
   Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen Int
genShipSize ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
size ->
   Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen Int
genShipSize ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
pos ->
      T -> Int -> Int
lookup T
fleet Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
digitMask
      Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
QC.==>
      T -> Int -> Int
lookup (Int -> T -> T
inc Int
size T
fleet) Int
pos Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== T -> Int -> Int
lookup T
fleet Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Int
posInt -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
size)

propDec :: T -> QC.Property
propDec :: T -> Property
propDec T
fleet =
   Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen Int
genShipSize ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
size ->
   Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen Int
genShipSize ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
pos ->
      T -> Int -> Int
lookup T
fleet Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
      Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
QC.==>
      T -> Int -> Int
lookup (Int -> T -> T
dec Int
size T
fleet) Int
pos Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== T -> Int -> Int
lookup T
fleet Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Bool -> Int
forall a. Enum a => a -> Int
fromEnum (Int
posInt -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
size)

propIncDec :: T -> QC.Property
propIncDec :: T -> Property
propIncDec T
fleet =
   Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll Gen Int
genShipSize ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
size ->
      T -> Int -> Int
lookup T
fleet Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
digitMask
      Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
QC.==>
      Int -> T -> T
dec Int
size (Int -> T -> T
inc Int
size T
fleet) T -> T -> Bool
forall a. Eq a => a -> a -> Bool
== T
fleet


instance QC.Arbitrary T where
   arbitrary :: Gen T
arbitrary = (Word32 -> T) -> Gen Word32 -> Gen T
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word32 -> T
Cons (Gen Word32 -> Gen T) -> Gen Word32 -> Gen T
forall a b. (a -> b) -> a -> b
$ (Word32, Word32) -> Gen Word32
forall a. Random a => (a, a) -> Gen a
QC.choose (Word32
forall a. Bounded a => a
minBound, Word32
forall a. Bounded a => a
maxBound)
   shrink :: T -> [T]
shrink = ([Int] -> T) -> [[Int]] -> [T]
forall a b. (a -> b) -> [a] -> [b]
map ([Int] -> T
fromSizes ([Int] -> T) -> ([Int] -> [Int]) -> [Int] -> T
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0)) ([[Int]] -> [T]) -> (T -> [[Int]]) -> T -> [T]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [[Int]]
forall a. Arbitrary a => a -> [a]
QC.shrink ([Int] -> [[Int]]) -> (T -> [Int]) -> T -> [[Int]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T -> [Int]
toSizes