diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 47a7fa96c4e8e689d4407a5dbb9d6d19854b51e3..c15e9591473807459f7e04db15608430ef0dc19b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,7 @@ Hlint: stage: Lint needs: [] script: - - nix-shell nix/lint.nix --run 'hlint .' + - nix-shell nix/lint.nix --run 'hlint . -j' Packages GHC 8.6.5 on Linux: stage: Linux Build diff --git a/nix/overlay-shpadoinkle.nix b/nix/overlay-shpadoinkle.nix index d455175e45ee898d735210880e02335eb0a04f4d..01fcf9055ea579d7e91d9883e10c8b225e490982 100644 --- a/nix/overlay-shpadoinkle.nix +++ b/nix/overlay-shpadoinkle.nix @@ -100,10 +100,10 @@ addDev = x: super.haskell.lib.appendConfigureFlags x [ "-f" "development" ]; - addTest = x: hpkgs: if isJS then super.haskell.lib.dontCheck x else (super.haskell.lib.appendConfigureFlags (super.haskell.lib.addBuildDepends x - (with hpkgs; [hspec QuickCheck quickcheck-classes quickcheck-classes-base ]) - ) [ "-f" "testing" ]); - + addTest = x: hpkgs: if isJS then super.haskell.lib.dontCheck x else + (super.haskell.lib.appendConfigureFlags (super.haskell.lib.addBuildDepends x + (with hpkgs; [hspec QuickCheck quickcheck-classes quickcheck-classes-base ]) + ) [ "-f" "testing" ]); in { @@ -118,8 +118,6 @@ in { url = "https://github.com/NixOS/nixpkgs/archive/${chrome-rev}.tar.gz"; }) {}).google-chrome; - - haskell = super.haskell // { packages = super.haskell.packages // { "${util.compilerjs}" = with super.haskell.lib; diff --git a/widgets/Shpadoinkle/Widgets/Form/Dropdown.hs b/widgets/Shpadoinkle/Widgets/Form/Dropdown.hs index 6c2955509d18e1d76e51696aee13b0bb68be23c2..90405ff451306f276d226b015c2a0282ba5cd772 100644 --- a/widgets/Shpadoinkle/Widgets/Form/Dropdown.hs +++ b/widgets/Shpadoinkle/Widgets/Form/Dropdown.hs @@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE ExtendedDefaultRules #-} @@ -51,6 +52,7 @@ deriving instance (Show (Selected p a), Show (Considered p a), Show a) => deriving instance (Read (Selected p a), Read (Considered p a), Read a, Ord a) => Read (Dropdown p a) deriving instance (Eq (Selected p a), Eq (Considered p a), Eq a) => Eq (Dropdown p a) deriving instance (Ord (Selected p a), Ord (Considered p a), Ord a) => Ord (Dropdown p a) +deriving instance (Foldable (ConsideredChoice p)) => Foldable (Dropdown p) deriving instance Generic (Dropdown p a) instance (ToJSON a, ToJSON (Selected p a), ToJSON (Considered p a)) => ToJSON (Dropdown p a) instance (FromJSON a, FromJSON (Selected p a), FromJSON (Considered p a), Ord a) => FromJSON (Dropdown p a) diff --git a/widgets/Shpadoinkle/Widgets/Types/Choice.hs b/widgets/Shpadoinkle/Widgets/Types/Choice.hs index 5fd49a47f71df77a218bdf7e00c36f6397a24f59..3bf38b30c8fa7f264458901f5bd7686140d19f4a 100644 --- a/widgets/Shpadoinkle/Widgets/Types/Choice.hs +++ b/widgets/Shpadoinkle/Widgets/Types/Choice.hs @@ -31,6 +31,7 @@ import Data.Proxy import Data.Set as Set import GHC.Generics (Generic) #ifdef TESTING +import Data.Monoid (Sum (..)) import Test.QuickCheck import Test.QuickCheck.Classes import Test.QuickCheck.Classes.Hspec @@ -404,6 +405,11 @@ instance Selection Choice 'Many where retain (Choice x _) (Choice y ys) = Choice (Set.intersection x ys <> y) ys +type family ToS (p :: Pick) :: Type -> Type where + ToS 'One = Maybe + ToS 'Many = Set + + class Selection f p => Deselection f (p :: Pick) where noselection :: (Foldable g, Ord a) => g a -> f p a deselect :: Ord a => f p a -> f p a @@ -417,6 +423,115 @@ instance Deselection Choice 'Many where deselect (Choice ys xs) = Choice mempty (ys <> xs) +#ifdef TESTING + + +class + ( Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Monoid (Selected p (Sum Int)) + , DemotePick p, PickToSet p + , Selected p (Sum Int) ~ ToS p (Sum Int) + , SetLike (ToS p) + , Selection f p + ) => PropableChoiceDe f p +instance + ( Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Monoid (Selected p (Sum Int)) + , DemotePick p, PickToSet p + , Selected p (Sum Int) ~ ToS p (Sum Int) + , SetLike (ToS p) + , Selection f p + ) => PropableChoiceDe f p + + +type instance Justice (Deselection f) p = PropableChoiceDe f p + + +instance Legal (Deselection f) where + legal' (_ :: Proxy (Deselection f)) (_ :: Proxy p) = + deselectionLaws (Proxy @(f p)) + + +deselectionLaws :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Monoid (Selected p (Sum Int)) + , Selected p (Sum Int) ~ ToS p (Sum Int) + , SetLike (ToS p) + , DemotePick p + ) => proxy (f p) -> Laws +deselectionLaws p = Laws ("Deselection '" <> show (demotePick @p)) + [ ("idempotence deselect", idempotenceSelect p) + , ("deselect select selected identity", dselectSelectSelectedIdentity p) + , ("selected deselect annihliation", selectedDeselectAnnihliation p) + , ("deselect keeps", deselectKeeps p) + , ("unselected passes through deselect keeps", unselectedPasses p) + , ("deselect unselected is full set", deselectFullSet p) + ] + + +idempotenceSelect, deselectFullSet + :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + ) => proxy (f p) -> Property +idempotenceSelect _ = property $ \(c :: f p (Sum Int)) -> + deselect (deselect c) == deselect c + + +deselectFullSet _ = property $ \(c :: f p (Sum Int)) -> + unselected (deselect c) == toSet c + + +dselectSelectSelectedIdentity + :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + ) => proxy (f p) -> Property +dselectSelectSelectedIdentity _ = property $ \(c :: f p (Sum Int)) x -> + selected (select (deselect c) x) == x + + +selectedDeselectAnnihliation + :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Monoid (Selected p (Sum Int)) + ) => proxy (f p) -> Property +selectedDeselectAnnihliation _ = property $ \(c :: f p (Sum Int)) -> + selected (deselect c) == mempty + + +deselectKeeps + :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Selected p (Sum Int) ~ ToS p (Sum Int) + , SetLike (ToS p) + ) => proxy (f p) -> Property +deselectKeeps _ = property $ \(c :: f p (Sum Int)) (x :: Selected p (Sum Int)) -> + toSet (x :: ToS p (Sum Int)) `isSubsetOf` toSet (deselect (select c x)) + + +unselectedPasses + :: forall proxy f (p :: Pick). + ( Deselection f p + , Propable1Ord (f p) + , Propable0 (Selected p (Sum Int)) + , Selected p (Sum Int) ~ ToS p (Sum Int) + , SetLike (ToS p) + ) => proxy (f p) -> Property +unselectedPasses _ = property $ \(c :: f p (Sum Int)) (x :: Selected p (Sum Int)) -> + toSet x `isSubsetOf` unselected (deselect (select c x)) +#endif + + next, nextLoop, prev, prevLoop :: (Selection f 'AtleastOne, Ord a) => f 'AtleastOne a -> f 'AtleastOne a next xs = maybe xs (select xs) . Set.lookupGT (selected xs) $ toSet xs nextLoop xs = maybe (unsafeSelectFirst xs) (select xs) . Set.lookupGT (selected xs) $ toSet xs diff --git a/widgets/Shpadoinkle/Widgets/Types/ConsideredChoice.hs b/widgets/Shpadoinkle/Widgets/Types/ConsideredChoice.hs index 6a41e03f9acc53dda6cb4f496fcde2757299572d..822db5d23c6f489dbcc543ed4cacfa7d82a938ba 100644 --- a/widgets/Shpadoinkle/Widgets/Types/ConsideredChoice.hs +++ b/widgets/Shpadoinkle/Widgets/Types/ConsideredChoice.hs @@ -1,6 +1,7 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} @@ -42,6 +43,7 @@ deriving instance (Show (Selected p a), Show (Considered p a), Show a) => deriving instance (Read (Selected p a), Read (Considered p a), Read a, Ord a) => Read (ConsideredChoice p a) deriving instance (Eq (Selected p a), Eq (Considered p a), Eq a) => Eq (ConsideredChoice p a) deriving instance (Ord (Selected p a), Ord (Considered p a), Ord a) => Ord (ConsideredChoice p a) +deriving instance (Foldable (Choice p), Foldable (Considered p)) => Foldable (ConsideredChoice p) deriving instance Generic (ConsideredChoice p a) instance (FromJSON a, FromJSON (Considered p a), FromJSON (Selected p a), Ord a) => FromJSON (ConsideredChoice p a) instance (ToJSON a, ToJSON (Considered p a), ToJSON (Selected p a)) => ToJSON (ConsideredChoice p a) diff --git a/widgets/Test/QuickCheck/Classes/FoldableOrd.hs b/widgets/Test/QuickCheck/Classes/FoldableOrd.hs new file mode 100644 index 0000000000000000000000000000000000000000..3d830c7372944ae636ed11953a947773fdad675e --- /dev/null +++ b/widgets/Test/QuickCheck/Classes/FoldableOrd.hs @@ -0,0 +1,170 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Test.QuickCheck.Classes.FoldableOrd + ( + foldableLaws + ) where + +import Control.Exception (ErrorCall, evaluate, try) +import Control.Monad.Trans.Class (lift) +import Test.QuickCheck hiding ((.&.)) +import Test.QuickCheck.Monadic (monadicIO) +import Test.QuickCheck.Property (Property) + +import qualified Data.Foldable as F +import qualified Data.Semigroup as SG + +import Test.QuickCheck.Classes.Internal + + +newtype ApplyOrd f a = ApplyOrd { unApplyOrd :: f a } +deriving instance (forall x. Eq x => Eq (f x), Eq a) => Eq (ApplyOrd f a) +deriving instance (forall x. Show x => Show (f x), Show a) => Show (ApplyOrd f a) +deriving instance + ( forall x. (Ord x, Arbitrary x) => Arbitrary (f x) + , Ord a + , Arbitrary a + ) => Arbitrary (ApplyOrd f a) + + +deriving instance Ord (Bottom Integer) +deriving instance Ord (VerySmallList Integer) + + +-- | Tests the following 'Foldable' properties: +-- +-- [/fold/] +-- @'fold' ≡ 'foldMap' 'id'@ +-- [/foldMap/] +-- @'foldMap' f ≡ 'foldr' ('mappend' . f) 'mempty'@ +-- [/foldr/] +-- @'foldr' f z t ≡ 'appEndo' ('foldMap' ('Endo' . f) t ) z@ +-- [/foldr'/] +-- @'foldr'' f z0 xs ≡ let f\' k x z = k '$!' f x z in 'foldl' f\' 'id' xs z0@ +-- [/foldr1/] +-- @'foldr1' f t ≡ let 'Just' (xs,x) = 'unsnoc' ('toList' t) in 'foldr' f x xs@ +-- [/foldl/] +-- @'foldl' f z t ≡ 'appEndo' ('getDual' ('foldMap' ('Dual' . 'Endo' . 'flip' f) t)) z@ +-- [/foldl'/] +-- @'foldl'' f z0 xs ≡ let f' x k z = k '$!' f z x in 'foldr' f\' 'id' xs z0@ +-- [/foldl1/] +-- @'foldl1' f t ≡ let x : xs = 'toList' t in 'foldl' f x xs@ +-- [/toList/] +-- @'F.toList' ≡ 'foldr' (:) []@ +-- [/null/] +-- @'null' ≡ 'foldr' ('const' ('const' 'False')) 'True'@ +-- [/length/] +-- @'length' ≡ 'getSum' . 'foldMap' ('const' ('Sum' 1))@ +-- +-- Note that this checks to ensure that @foldl\'@ and @foldr\'@ +-- are suitably strict. +foldableLaws :: forall proxy f. + (Foldable f, forall a. Show a => Show (f a), forall a. (Arbitrary a, Ord a) => Arbitrary (f a)) + => proxy f -> Laws +foldableLaws = foldableLawsInternal + +foldableLawsInternal :: forall proxy f. + (Foldable f, forall a. Show a => Show (f a), forall a. (Arbitrary a, Ord a) => Arbitrary (f a)) + => proxy f -> Laws +foldableLawsInternal p = Laws "Foldable" + [ (,) "fold" $ property $ \(ApplyOrd (a :: f (VerySmallList Integer))) -> + F.fold a == F.foldMap id a + , (,) "foldMap" $ property $ \(ApplyOrd (a :: f Integer)) (e :: QuadraticEquation) -> + let f = VerySmallList . return . runQuadraticEquation e + in F.foldMap f a == F.foldr (mappend . f) mempty a + , (,) "foldr" $ property $ \(e :: LinearEquationTwo) (z :: Integer) (ApplyOrd (t :: f Integer)) -> + let f = runLinearEquationTwo e + in F.foldr f z t == SG.appEndo (foldMap (SG.Endo . f) t) z + , (,) "foldr'" (foldableFoldr' p) + , (,) "foldl" $ property $ \(e :: LinearEquationTwo) (z :: Integer) (ApplyOrd (t :: f Integer)) -> + let f = runLinearEquationTwo e + in F.foldl f z t == SG.appEndo (SG.getDual (F.foldMap (SG.Dual . SG.Endo . flip f) t)) z + , (,) "foldl'" (foldableFoldl' p) + , (,) "foldl1" $ property $ \(e :: LinearEquationTwo) (ApplyOrd (t :: f Integer)) -> + case compatToList t of + [] -> True + x : xs -> + let f = runLinearEquationTwo e + in F.foldl1 f t == F.foldl f x xs + , (,) "foldr1" $ property $ \(e :: LinearEquationTwo) (ApplyOrd (t :: f Integer)) -> + case unsnoc (compatToList t) of + Nothing -> True + Just (xs,x) -> + let f = runLinearEquationTwo e + in F.foldr1 f t == F.foldr f x xs + , (,) "toList" $ property $ \(ApplyOrd (t :: f Integer)) -> + eq1 (F.toList t) (F.foldr (:) [] t) +#if MIN_VERSION_base(4,8,0) + , (,) "null" $ property $ \(ApplyOrd (t :: f Integer)) -> + null t == F.foldr (const (const False)) True t + , (,) "length" $ property $ \(ApplyOrd (t :: f Integer)) -> + F.length t == SG.getSum (F.foldMap (const (SG.Sum 1)) t) +#endif + ] + +unsnoc :: [a] -> Maybe ([a],a) +unsnoc [] = Nothing +unsnoc [x] = Just ([],x) +unsnoc (x:y:xs) = fmap (\(bs,b) -> (x:bs,b)) (unsnoc (y : xs)) + +compatToList :: Foldable f => f a -> [a] +compatToList = foldMap (\x -> [x]) + +foldableFoldl' :: forall proxy f. + (Foldable f, forall a. Show a => Show (f a), forall a. (Arbitrary a, Ord a) => Arbitrary (f a)) + => proxy f -> Property +foldableFoldl' _ = property $ \(_ :: ChooseSecond) (_ :: LastNothing) (ApplyOrd (xs :: f (Bottom Integer))) -> + monadicIO $ do + let f :: Integer -> Bottom Integer -> Integer + f a b = case b of + BottomUndefined -> error "foldableFoldl' example" + BottomValue v -> if even v + then a + else v + z0 = 0 + r1 <- lift $ do + let f' x k z = k $! f z x + e <- try (evaluate (F.foldr f' id xs z0)) + case e of + Left (_ :: ErrorCall) -> return Nothing + Right i -> return (Just i) + r2 <- lift $ do + e <- try (evaluate (F.foldl' f z0 xs)) + case e of + Left (_ :: ErrorCall) -> return Nothing + Right i -> return (Just i) + return (r1 == r2) + +foldableFoldr' :: forall proxy f. + (Foldable f, forall a. Show a => Show (f a), forall a. (Arbitrary a, Ord a) => Arbitrary (f a)) + => proxy f -> Property +foldableFoldr' _ = property $ \(_ :: ChooseFirst) (_ :: LastNothing) (ApplyOrd (xs :: f (Bottom Integer))) -> + monadicIO $ do + let f :: Bottom Integer -> Integer -> Integer + f a b = case a of + BottomUndefined -> error "foldableFoldl' example" + BottomValue v -> if even v + then v + else b + z0 = 0 + r1 <- lift $ do + let f' k x z = k $! f x z + e <- try (evaluate (F.foldl f' id xs z0)) + case e of + Left (_ :: ErrorCall) -> return Nothing + Right i -> return (Just i) + r2 <- lift $ do + e <- try (evaluate (F.foldr' f z0 xs)) + case e of + Left (_ :: ErrorCall) -> return Nothing + Right i -> return (Just i) + return (r1 == r2) + +{-# ANN module ("HLint: ignore" :: String) #-} diff --git a/widgets/Test/QuickCheck/Classes/Hspec.hs b/widgets/Test/QuickCheck/Classes/Hspec.hs index 988dfaecf965c848a6a17706e5b3283428047032..378f11d41f0ee5dd873a27639dd1adbb0a70de11 100644 --- a/widgets/Test/QuickCheck/Classes/Hspec.hs +++ b/widgets/Test/QuickCheck/Classes/Hspec.hs @@ -16,13 +16,14 @@ module Test.QuickCheck.Classes.Hspec where -import Control.Applicative (Alternative) +import Control.Applicative (Alternative) import Data.Kind import Data.Proxy import Test.Hspec import Test.QuickCheck import Test.QuickCheck.Classes +import qualified Test.QuickCheck.Classes.FoldableOrd as Ord toSpec :: Laws -> Spec @@ -87,7 +88,7 @@ type instance Justice Applicative f = Propable1 f type instance Justice Alternative f = Propable1 f type instance Justice Monad f = Propable1 f type instance Justice Show a = Propable0 a --- type instance Justice Foldable f = Propable1Ord f +type instance Justice Foldable f = Propable1Ord f type instance Justice Traversable f = Propable1 f -- foldableLawsOrd :: forall proxy f. @@ -110,5 +111,5 @@ instance Legal Applicative where legal' _ = applicativeLaws instance Legal Alternative where legal' _ = alternativeLaws instance Legal Monad where legal' _ = monadLaws instance Legal Show where legal' _ = showLaws --- instance Legal Foldable where legal' _ = foldableLawsOrd +instance Legal Foldable where legal' _ = Ord.foldableLaws -- instance Legal Traversable where legal' _ = traversableLaws diff --git a/widgets/package.yaml b/widgets/package.yaml index 54f225f6318e137c4b59fd3b562a0fb7a91367b3..ba8ece1053564329e80eda1d887a831bc2903036 100644 --- a/widgets/package.yaml +++ b/widgets/package.yaml @@ -76,8 +76,10 @@ library: then: exposed-modules: - Test.QuickCheck.Classes.Hspec + - Test.QuickCheck.Classes.FoldableOrd cpp-options: -DTESTING dependencies: + - transformers - QuickCheck - quickcheck-classes - quickcheck-classes-base diff --git a/widgets/tests/Test.hs b/widgets/tests/Test.hs index acea384989874634afecf028430693f34c7ed9d9..021aed3109fef8358e6b7561e0b2ef9966145ff6 100644 --- a/widgets/tests/Test.hs +++ b/widgets/tests/Test.hs @@ -1,7 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE PolyKinds #-} @@ -18,12 +17,10 @@ module Main where import Control.Applicative (Alternative) -import Data.Kind import Data.Monoid (Sum) import Data.Set as Set import Test.Hspec -import Test.QuickCheck import Test.QuickCheck.Classes.Hspec import Shpadoinkle.Widgets.Form.Dropdown @@ -34,79 +31,6 @@ instance Show (a -> b) where show _ = "(a -> b)" -type TestConstraints a = - ( Arbitrary a - , Show a - , Eq a - ) - - -type ChoiceTest f = - ( ChoiceWith Arbitrary f - , ChoiceWith Show f - , ChoiceWith Eq f - ) - - -type ChoiceClass - (c :: (Pick -> Type -> Type) -> Pick -> Constraint) - (f :: Pick -> Type -> Type) = - ( c f 'One - , c f 'AtleastOne - , c f 'Many - ) - - -type ChoiceWith (c :: Type -> Constraint) f = - ( c (f 'One (Sum Int)) - , c (f 'AtleastOne (Sum Int)) - , c (f 'Many (Sum Int)) - ) - - - -deselectionProps - :: forall (f :: Pick -> Type -> Type) - . ( TestConstraints (f 'One (Sum Int)) - , TestConstraints (f 'Many (Sum Int)) - , Deselection f 'One - , Deselection f 'Many - ) => Spec -deselectionProps = do - deselectionProps' @f @'One - deselectionProps' @f @'Many - - -deselectionProps' - :: forall (f :: Pick -> Type -> Type) (p :: Pick) (s :: Type -> Type) - . ( TestConstraints (f p (Sum Int)) - , TestConstraints (s (Sum Int)) - , Deselection f p - , Selected p (Sum Int) ~ s (Sum Int), SetLike s, Monoid (s (Sum Int)) - ) => Spec -deselectionProps' = describe "Deselection" $ do - - it "idempotence deselect" . property $ \(c :: f p (Sum Int)) -> - deselect (deselect c) == deselect c - - it "deselect select selected identity" . property $ \(c :: f p (Sum Int)) x -> - selected (select (deselect c) x) == x - - it "selected deselect annihliation" . property $ \(c :: f p (Sum Int)) -> - selected (deselect c) == mempty - - it "deselect keeps" . property $ \(c :: f p (Sum Int)) x -> - toSet x `isSubsetOf` toSet (deselect (select c x)) - - it "unselected passes through deselect keeps" . property $ \(c :: f p (Sum Int)) (x :: Selected p (Sum Int)) -> - toSet x `isSubsetOf` unselected (deselect (select c x)) - - it "deselect unselected is full set" . property $ \(c :: f p (Sum Int)) -> - unselected (deselect c) == toSet c - - - - main :: IO () main = hspec $ do @@ -146,6 +70,7 @@ main = hspec $ do legal @Applicative @(Remote Int) legal @Monad @(Remote Int) legal @Alternative @(Remote Int) + legal @Foldable @(Remote Int) describe "Input" $ do @@ -156,6 +81,7 @@ main = hspec $ do legal @Functor @Input legal @Applicative @Input legal @Monad @Input + legal @Foldable @Input describe "Validated" $ do @@ -166,49 +92,55 @@ main = hspec $ do legal @Functor @(Validated Int) legal @Applicative @(Validated Int) legal @Monad @(Validated Int) + legal @Foldable @(Validated Int) describe "Choice" $ do describe "'One" $ do - legal @Eq @(Choice 'One Int) - legal @Ord @(Choice 'One Int) - legal @Show @(Choice 'One Int) - legal @Semigroup @(Choice 'One (Sum Int)) - legal @Monoid @(Choice 'One (Sum Int)) - legal @SetLike @(Choice 'One) - legal @(Selection Choice) @'One + legal @Eq @(Choice 'One Int) + legal @Ord @(Choice 'One Int) + legal @Show @(Choice 'One Int) + legal @Semigroup @(Choice 'One (Sum Int)) + legal @Monoid @(Choice 'One (Sum Int)) + legal @SetLike @(Choice 'One) + legal @Foldable @(Choice 'One) + legal @(Selection Choice) @'One + legal @(Deselection Choice) @'One describe "'AtleastOne" $ do - legal @Eq @(Choice 'AtleastOne Int) - legal @Ord @(Choice 'AtleastOne Int) - legal @Show @(Choice 'AtleastOne Int) - legal @Semigroup @(Choice 'AtleastOne (Sum Int)) - legal @SetLike @(Choice 'AtleastOne) - legal @(Selection Choice) @'AtleastOne + legal @Eq @(Choice 'AtleastOne Int) + legal @Ord @(Choice 'AtleastOne Int) + legal @Show @(Choice 'AtleastOne Int) + legal @Semigroup @(Choice 'AtleastOne (Sum Int)) + legal @SetLike @(Choice 'AtleastOne) + legal @Foldable @(Choice 'AtleastOne) + legal @(Selection Choice) @'AtleastOne describe "'Many" $ do - legal @Eq @(Choice 'Many Int) - legal @Ord @(Choice 'Many Int) - legal @Show @(Choice 'Many Int) - legal @Semigroup @(Choice 'Many (Sum Int)) - legal @Monoid @(Choice 'Many (Sum Int)) - legal @SetLike @(Choice 'Many) - legal @(Selection Choice) @'Many - - deselectionProps @Choice + legal @Eq @(Choice 'Many Int) + legal @Ord @(Choice 'Many Int) + legal @Show @(Choice 'Many Int) + legal @Semigroup @(Choice 'Many (Sum Int)) + legal @Monoid @(Choice 'Many (Sum Int)) + legal @SetLike @(Choice 'Many) + legal @Foldable @(Choice 'Many) + legal @(Selection Choice) @'Many + legal @(Deselection Choice) @'Many describe "ConsideredChoice" $ do describe "'One" $ do - legal @Eq @(ConsideredChoice 'One Int) - legal @Ord @(ConsideredChoice 'One Int) - legal @Show @(ConsideredChoice 'One Int) - legal @Semigroup @(ConsideredChoice 'One (Sum Int)) - legal @Monoid @(ConsideredChoice 'One (Sum Int)) - legal @SetLike @(ConsideredChoice 'One) - legal @(Selection ConsideredChoice) @'One + legal @Eq @(ConsideredChoice 'One Int) + legal @Ord @(ConsideredChoice 'One Int) + legal @Show @(ConsideredChoice 'One Int) + legal @Semigroup @(ConsideredChoice 'One (Sum Int)) + legal @Monoid @(ConsideredChoice 'One (Sum Int)) + legal @SetLike @(ConsideredChoice 'One) + legal @Foldable @(ConsideredChoice 'One) + legal @(Selection ConsideredChoice) @'One + legal @(Deselection ConsideredChoice) @'One describe "'AtleastOne" $ do legal @Eq @(ConsideredChoice 'AtleastOne Int) @@ -216,30 +148,33 @@ main = hspec $ do legal @Show @(ConsideredChoice 'AtleastOne Int) legal @Semigroup @(ConsideredChoice 'AtleastOne (Sum Int)) legal @SetLike @(ConsideredChoice 'AtleastOne) + legal @Foldable @(ConsideredChoice 'AtleastOne) legal @(Selection ConsideredChoice) @'AtleastOne describe "'Many" $ do - legal @Eq @(ConsideredChoice 'Many Int) - legal @Ord @(ConsideredChoice 'Many Int) - legal @Show @(ConsideredChoice 'Many Int) - legal @Semigroup @(ConsideredChoice 'Many (Sum Int)) - legal @Monoid @(ConsideredChoice 'Many (Sum Int)) - legal @SetLike @(ConsideredChoice 'Many) - legal @(Selection ConsideredChoice) @'Many - - deselectionProps @ConsideredChoice + legal @Eq @(ConsideredChoice 'Many Int) + legal @Ord @(ConsideredChoice 'Many Int) + legal @Show @(ConsideredChoice 'Many Int) + legal @Semigroup @(ConsideredChoice 'Many (Sum Int)) + legal @Monoid @(ConsideredChoice 'Many (Sum Int)) + legal @SetLike @(ConsideredChoice 'Many) + legal @Foldable @(ConsideredChoice 'Many) + legal @(Selection ConsideredChoice) @'Many + legal @(Deselection ConsideredChoice) @'Many describe "Dropdown" $ do describe "'One" $ do - legal @Eq @(Dropdown 'One Int) - legal @Ord @(Dropdown 'One Int) - legal @Show @(Dropdown 'One Int) - legal @Semigroup @(Dropdown 'One (Sum Int)) - legal @Monoid @(Dropdown 'One (Sum Int)) - legal @SetLike @(Dropdown 'One) - legal @(Selection Dropdown) @'One + legal @Eq @(Dropdown 'One Int) + legal @Ord @(Dropdown 'One Int) + legal @Show @(Dropdown 'One Int) + legal @Semigroup @(Dropdown 'One (Sum Int)) + legal @Monoid @(Dropdown 'One (Sum Int)) + legal @SetLike @(Dropdown 'One) + legal @Foldable @(Dropdown 'One) + legal @(Selection Dropdown) @'One + legal @(Deselection Dropdown) @'One describe "'AtleastOne" $ do legal @Eq @(Dropdown 'AtleastOne Int) @@ -247,18 +182,16 @@ main = hspec $ do legal @Show @(Dropdown 'AtleastOne Int) legal @Semigroup @(Dropdown 'AtleastOne (Sum Int)) legal @SetLike @(Dropdown 'AtleastOne) + legal @Foldable @(Dropdown 'AtleastOne) legal @(Selection Dropdown) @'AtleastOne describe "'Many" $ do - legal @Eq @(Dropdown 'Many Int) - legal @Ord @(Dropdown 'Many Int) - legal @Show @(Dropdown 'Many Int) - legal @Semigroup @(Dropdown 'Many (Sum Int)) - legal @Monoid @(Dropdown 'Many (Sum Int)) - legal @SetLike @(Dropdown 'Many) - legal @(Selection Dropdown) @'Many - - deselectionProps @Dropdown - - -{-# ANN module ("HLint: ignore" :: String) #-} + legal @Eq @(Dropdown 'Many Int) + legal @Ord @(Dropdown 'Many Int) + legal @Show @(Dropdown 'Many Int) + legal @Semigroup @(Dropdown 'Many (Sum Int)) + legal @Monoid @(Dropdown 'Many (Sum Int)) + legal @SetLike @(Dropdown 'Many) + legal @Foldable @(Dropdown 'Many) + legal @(Selection Dropdown) @'Many + legal @(Deselection Dropdown) @'Many