@@ -1,14 +1,103 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE StandaloneDeriving #-}
5+{-# LANGUAGE TypeOperators #-}
26
37-- TODO upstream somwhere else?
48module Data.Monoid.DecidablyEmpty where
59
10+import Data.Functor.Identity
11+import Data.Functor.Const
12+import Data.Monoid
13+import Data.Maybe (isNothing)
14+import Data.Ord
615import Data.Proxy
16+import Data.Semigroup hiding (First, Last)
17+import GHC.Generics
718
19+import qualified Data.IntSet as IntSet
20+import qualified Data.IntMap as IntMap
21+import qualified Data.Map as Map
22+import qualified Data.Sequence as Seq
23+import qualified Data.Set as Set
24+
25+import Data.GADT.Compare
26+import qualified Data.Dependent.Map as DMap
27+
28+-- | A 'DecidablyEmpty' is one where it can be computed whether or not an
29+-- arbitrary value is 'mempty'.
30+--
31+-- By using this class rather than 'Eq', we avoid unnecessary constraining the
32+-- contents of 'Functor's. This makes it possible to efficiently combine and/or
33+-- nest patch maps with 'Eq'-lacking values (e.g. functions) at the leaves.
834class Monoid a => DecidablyEmpty a where
935 isEmpty :: a -> Bool
1036 default isEmpty :: Eq a => a -> Bool
1137 isEmpty = (==) mempty
1238
13−instance DecidablyEmpty (Proxy a) where
14− isEmpty ~Proxy = True
39+-- base
40+
41+instance DecidablyEmpty Ordering
42+instance DecidablyEmpty ()
43+instance DecidablyEmpty Any
44+instance DecidablyEmpty All
45+-- instance DecidablyEmpty Lifetime
46+-- instance DecidablyEmpty Event
47+instance DecidablyEmpty [a] where
48+ isEmpty = null
49+instance Semigroup a => DecidablyEmpty (Maybe a) where
50+ isEmpty = isNothing
51+#if MIN_VERSION_base(4,11,0)
52+deriving instance DecidablyEmpty a => DecidablyEmpty (Down a)
53+#endif
54+deriving instance (Num a, DecidablyEmpty a) => DecidablyEmpty (Product a)
55+deriving instance (DecidablyEmpty a, Num a) => DecidablyEmpty (Sum a)
56+deriving instance DecidablyEmpty a => DecidablyEmpty (Dual a)
57+deriving instance Semigroup a => DecidablyEmpty (First a)
58+deriving instance Semigroup a => DecidablyEmpty (Last a)
59+deriving instance DecidablyEmpty a => DecidablyEmpty (Identity a)
60+deriving instance Semigroup a => DecidablyEmpty (Option a)
61+deriving instance DecidablyEmpty m => DecidablyEmpty (WrappedMonoid m)
62+instance (Ord a, Bounded a) => DecidablyEmpty (Max a)
63+instance (Ord a, Bounded a) => DecidablyEmpty (Min a)
64+instance DecidablyEmpty (U1 p)
65+instance DecidablyEmpty (Proxy s)
66+#if MIN_VERSION_base(4,12,0)
67+deriving instance DecidablyEmpty (f p) => DecidablyEmpty (Rec1 f p)
68+#endif
69+deriving instance DecidablyEmpty a => DecidablyEmpty (Const a b)
70+deriving instance DecidablyEmpty c => DecidablyEmpty (K1 i c p)
71+instance (DecidablyEmpty (f p), DecidablyEmpty (g p)) => DecidablyEmpty ((f :*: g) p) where
72+ isEmpty (x :*: y) = isEmpty x && isEmpty y
73+#if MIN_VERSION_base(4,12,0)
74+deriving instance DecidablyEmpty (f p) => DecidablyEmpty (M1 i c f p)
75+deriving instance DecidablyEmpty (f (g p)) => DecidablyEmpty ((f :.: g) p)
76+#endif
77+
78+instance (DecidablyEmpty a, DecidablyEmpty b) => DecidablyEmpty (a, b) where
79+ isEmpty (a, b) = isEmpty a && isEmpty b
80+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c) => DecidablyEmpty (a, b, c) where
81+ isEmpty (a, b, c) = isEmpty a && isEmpty b && isEmpty c
82+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d) => DecidablyEmpty (a, b, c, d) where
83+ isEmpty (a, b, c, d) = isEmpty a && isEmpty b && isEmpty c && isEmpty d
84+instance (DecidablyEmpty a, DecidablyEmpty b, DecidablyEmpty c, DecidablyEmpty d, DecidablyEmpty e) => DecidablyEmpty (a, b, c, d, e) where
85+ isEmpty (a, b, c, d, e) = isEmpty a && isEmpty b && isEmpty c && isEmpty d && isEmpty e
86+
87+-- containers
88+
89+instance DecidablyEmpty IntSet.IntSet where
90+ isEmpty = IntSet.null
91+instance DecidablyEmpty (IntMap.IntMap v) where
92+ isEmpty = IntMap.null
93+instance Ord k => DecidablyEmpty (Map.Map k v) where
94+ isEmpty = Map.null
95+instance DecidablyEmpty (Seq.Seq v) where
96+ isEmpty = Seq.null
97+instance Ord k => DecidablyEmpty (Set.Set k) where
98+ isEmpty = Set.null
99+
100+-- dependent-map
101+
102+instance GCompare k => DecidablyEmpty (DMap.DMap k v) where
103+ isEmpty = DMap.null