testMonoidProperties :: forall collection
                      . ( Monoid collection, IsList collection, Eq collection, Show collection
                        , Typeable collection, Typeable (Element collection)
                        , Element collection ~ Item collection
                        , Eq (Item collection), Show (Item collection)
                        )
                     => Proxy collection
                     -> Gen (Element collection)
                     -> Test
testMonoidProperties proxy genElement = Group "Monoid"
    [ Property "mempty <> x == x" $ withElements $ \l -> let col = fromListP proxy l in (col <> mempty) === col
    , Property "x <> mempty == x" $ withElements $ \l -> let col = fromListP proxy l in (mempty <> col) === col
    , Property "x1 <> x2 == x1|x2" $ with2Elements $ \(l1,l2) ->
        (fromListP proxy l1 <> fromListP proxy l2) === fromListP proxy (l1 <> l2)
    , Property "mconcat [map fromList [e]] = fromList (concat [e])" $ withNElements $ \l ->
        mconcat (fmap (fromListP proxy) l) === fromListP proxy (mconcat l)
    ]
  where
    withElements f = forAll (generateListOfElement genElement) f
    with2Elements f = forAll ((,) <$> generateListOfElement genElement <*> generateListOfElement genElement) f
    withNElements f = forAll (generateListOfElementMaxN 5 (generateListOfElement genElement)) f

-- | test the Foundation's @Collection@ class.
--
testMonoidProperties :: forall collection
                      . ( Monoid collection, IsList collection, Eq collection, Show collection
                        , Typeable collection, Typeable (Element collection)
                        , Element collection ~ Item collection
                        , Eq (Item collection), Show (Item collection)
                        )
                     => Proxy collection
                     -> Gen (Element collection)
                     -> Test
testMonoidProperties proxy genElement = Group "Monoid"
    [ Property "mempty <> x == x" $ withElements $ \l -> let col = fromListP proxy l in (col <> mempty) === col
    , Property "x <> mempty == x" $ withElements $ \l -> let col = fromListP proxy l in (mempty <> col) === col
    , Property "x1 <> x2 == x1|x2" $ with2Elements $ \(l1,l2) ->
        (fromListP proxy l1 <> fromListP proxy l2) === fromListP proxy (l1 <> l2)
    , Property "mconcat [map fromList [e]] = fromList (concat [e])" $ withNElements $ \l ->
        mconcat (fmap (fromListP proxy) l) === fromListP proxy (mconcat l)
    ]
  where
    withElements f = forAll (generateListOfElement genElement) f
    with2Elements f = forAll ((,) <$> generateListOfElement genElement <*> generateListOfElement genElement) f
    withNElements f = forAll (generateListOfElementMaxN 5 (generateListOfElement genElement)) f

-- | test the Foundation's @Collection@ class.
--
testMonoidProperties proxy genElement = Group "Monoid"
    [ Property "mempty <> x == x" $ withElements $ \l -> let col = fromListP proxy l in (col <> mempty) === col
    , Property "x <> mempty == x" $ withElements $ \l -> let col = fromListP proxy l in (mempty <> col) === col
    , Property "x1 <> x2 == x1|x2" $ with2Elements $ \(l1,l2) ->
        (fromListP proxy l1 <> fromListP proxy l2) === fromListP proxy (l1 <> l2)
    , Property "mconcat [map fromList [e]] = fromList (concat [e])" $ withNElements $ \l ->
        mconcat (fmap (fromListP proxy) l) === fromListP proxy (mconcat l)
    ]
  where
    withElements f = forAll (generateListOfElement genElement) f
    with2Elements f = forAll ((,) <$> generateListOfElement genElement <*> generateListOfElement genElement) f
    withNElements f = forAll (generateListOfElementMaxN 5 (generateListOfElement genElement)) f

-- | test the Foundation's @Collection@ class.
--