55{-# LANGUAGE DeriveDataTypeable #-}
66{-# LANGUAGE DeriveGeneric #-}
77{-# LANGUAGE DeriveLift #-}
8+ {-# LANGUAGE PatternSynonyms #-}
89{-# LANGUAGE StandaloneDeriving #-}
910{-# LANGUAGE Safe #-}
11+ {-# LANGUAGE TemplateHaskellQuotes #-}
12+ {-# LANGUAGE ViewPatterns #-}
1013#endif
1114
1215#include "containers.h"
@@ -74,7 +77,11 @@ module Data.Graph (
7477
7578
7679 -- * Strongly Connected Components
77- , SCC (.. )
80+ , SCC (..
81+ #ifdef __GLASGOW_HASKELL__
82+ , CyclicSCC
83+ #endif
84+ )
7885
7986 -- ** Construction
8087 , stronglyConnComp
@@ -107,6 +114,9 @@ import Data.Tree (Tree(Node), Forest)
107114
108115-- std interfaces
109116import Data.Foldable as F
117+ #if MIN_VERSION_base(4,18,0)
118+ import qualified Data.Foldable1 as F1
119+ #endif
110120import Control.DeepSeq (NFData (rnf ))
111121import Data.Maybe
112122import Data.Array
@@ -117,14 +127,16 @@ import Data.Array.Unboxed ( UArray )
117127import qualified Data.Array as UA
118128#endif
119129import qualified Data.List as L
130+ import Data.List.NonEmpty (NonEmpty (.. ))
131+ import qualified Data.List.NonEmpty as NE
120132import Data.Functor.Classes
121133#if !MIN_VERSION_base(4,11,0)
122134import Data.Semigroup (Semigroup (.. ))
123135#endif
124136#ifdef __GLASGOW_HASKELL__
125137import GHC.Generics (Generic , Generic1 )
126138import Data.Data (Data )
127- import Language.Haskell.TH.Syntax (Lift )
139+ import Language.Haskell.TH.Syntax (Lift ( .. ) )
128140-- See Note [ Template Haskell Dependencies ]
129141import Language.Haskell.TH ()
130142#endif
@@ -139,15 +151,26 @@ default ()
139151-------------------------------------------------------------------------
140152
141153-- | Strongly connected component.
142- data SCC vertex = AcyclicSCC vertex -- ^ A single vertex that is not
143- -- in any cycle.
144- | CyclicSCC [vertex ] -- ^ A maximal set of mutually
145- -- reachable vertices.
154+ data SCC vertex
155+ = AcyclicSCC vertex
156+ -- ^ A single vertex that is not in any cycle.
157+ | NECyclicSCC {- # UNPACK #-} !(NonEmpty vertex )
158+ -- ^ A maximal set of mutually reachable vertices.
159+ --
160+ -- @since 0.7.0
146161 deriving ( Eq -- ^ @since 0.5.9
147162 , Show -- ^ @since 0.5.9
148163 , Read -- ^ @since 0.5.9
149164 )
150165
166+ -- | Partial pattern synonym for backward compatibility with @containers < 0.7@.
167+ pattern CyclicSCC :: [vertex ] -> SCC vertex
168+ pattern CyclicSCC xs <- NECyclicSCC (NE. toList -> xs) where
169+ CyclicSCC [] = error " CyclicSCC: an argument cannot be an empty list"
170+ CyclicSCC (x : xs) = NECyclicSCC (x :| xs)
171+
172+ {-# COMPLETE AcyclicSCC, CyclicSCC #-}
173+
151174#ifdef __GLASGOW_HASKELL__
152175-- | @since 0.5.9
153176deriving instance Data vertex => Data (SCC vertex )
@@ -158,47 +181,65 @@ deriving instance Generic1 SCC
158181-- | @since 0.5.9
159182deriving instance Generic (SCC vertex )
160183
184+ -- There is no instance Lift (NonEmpty v) before template-haskell-2.15.
185+ #if MIN_VERSION_template_haskell(2,15,0)
161186-- | @since 0.6.6
162187deriving instance Lift vertex => Lift (SCC vertex )
188+ #else
189+ instance Lift vertex => Lift (SCC vertex ) where
190+ lift (AcyclicSCC v) = [| AcyclicSCC v | ]
191+ lift (NECyclicSCC (v :| vs)) = [| NECyclicSCC (v :| vs) | ]
192+ #endif
193+
163194#endif
164195
165196-- | @since 0.5.9
166197instance Eq1 SCC where
167198 liftEq eq (AcyclicSCC v1) (AcyclicSCC v2) = eq v1 v2
168- liftEq eq (CyclicSCC vs1) (CyclicSCC vs2) = liftEq eq vs1 vs2
199+ liftEq eq (NECyclicSCC vs1) (NECyclicSCC vs2) = liftEq eq vs1 vs2
169200 liftEq _ _ _ = False
170201-- | @since 0.5.9
171202instance Show1 SCC where
172203 liftShowsPrec sp _sl d (AcyclicSCC v) = showsUnaryWith sp " AcyclicSCC" d v
173- liftShowsPrec _sp sl d (CyclicSCC vs) = showsUnaryWith (const sl) " CyclicSCC " d vs
204+ liftShowsPrec sp sl d (NECyclicSCC vs) = showsUnaryWith (liftShowsPrec sp sl) " NECyclicSCC " d vs
174205-- | @since 0.5.9
175206instance Read1 SCC where
176207 liftReadsPrec rp rl = readsData $
177208 readsUnaryWith rp " AcyclicSCC" AcyclicSCC <>
209+ readsUnaryWith (liftReadsPrec rp rl) " NECyclicSCC" NECyclicSCC <>
178210 readsUnaryWith (const rl) " CyclicSCC" CyclicSCC
179211
180212-- | @since 0.5.9
181213instance F. Foldable SCC where
182214 foldr c n (AcyclicSCC v) = c v n
183- foldr c n (CyclicSCC vs) = foldr c n vs
215+ foldr c n (NECyclicSCC vs) = foldr c n vs
216+
217+ #if MIN_VERSION_base(4,18,0)
218+ -- | @since 0.7.0
219+ instance F1. Foldable1 SCC where
220+ foldMap1 f (AcyclicSCC v) = f v
221+ foldMap1 f (NECyclicSCC vs) = F1. foldMap1 f vs
222+ -- TODO define more methods
223+ #endif
184224
185225-- | @since 0.5.9
186226instance Traversable SCC where
187- -- We treat the non-empty cyclic case specially to cut one
188- -- fmap application.
189227 traverse f (AcyclicSCC vertex) = AcyclicSCC <$> f vertex
190- traverse _f (CyclicSCC [] ) = pure (CyclicSCC [] )
191- traverse f (CyclicSCC (x : xs)) =
192- liftA2 (\ x' xs' -> CyclicSCC (x' : xs')) (f x) (traverse f xs)
228+ -- Avoid traverse from instance Traversable NonEmpty,
229+ -- it is redundantly lazy.
230+ traverse f (NECyclicSCC (x :| xs)) =
231+ liftA2 (\ x' xs' -> NECyclicSCC (x' :| xs')) (f x) (traverse f xs)
193232
194233instance NFData a => NFData (SCC a ) where
195234 rnf (AcyclicSCC v) = rnf v
196- rnf (CyclicSCC vs) = rnf vs
235+ rnf (NECyclicSCC vs) = rnf vs
197236
198237-- | @since 0.5.4
199238instance Functor SCC where
200239 fmap f (AcyclicSCC v) = AcyclicSCC (f v)
201- fmap f (CyclicSCC vs) = CyclicSCC (fmap f vs)
240+ -- Avoid fmap from instance Functor NonEmpty,
241+ -- it is redundantly lazy.
242+ fmap f (NECyclicSCC (x :| xs)) = NECyclicSCC (f x :| map f xs)
202243
203244-- | The vertices of a list of strongly connected components.
204245flattenSCCs :: [SCC a ] -> [a ]
@@ -207,7 +248,7 @@ flattenSCCs = concatMap flattenSCC
207248-- | The vertices of a strongly connected component.
208249flattenSCC :: SCC vertex -> [vertex ]
209250flattenSCC (AcyclicSCC v) = [v]
210- flattenSCC (CyclicSCC vs) = vs
251+ flattenSCC (NECyclicSCC vs) = NE. toList vs
211252
212253-- | \(O((V+E) \log V)\). The strongly connected components of a directed graph,
213254-- reverse topologically sorted.
@@ -229,7 +270,8 @@ stronglyConnComp edges0
229270 = map get_node (stronglyConnCompR edges0)
230271 where
231272 get_node (AcyclicSCC (n, _, _)) = AcyclicSCC n
232- get_node (CyclicSCC triples) = CyclicSCC [n | (n,_,_) <- triples]
273+ get_node (NECyclicSCC ((n0, _, _) :| triples)) =
274+ NECyclicSCC (n0 :| [n | (n, _, _) <- triples])
233275{-# INLINABLE stronglyConnComp #-}
234276
235277-- | \(O((V+E) \log V)\). The strongly connected components of a directed graph,
@@ -258,11 +300,12 @@ stronglyConnCompR edges0
258300 where
259301 (graph, vertex_fn,_) = graphFromEdges edges0
260302 forest = scc graph
261- decode (Node v [] ) | mentions_itself v = CyclicSCC [vertex_fn v]
303+
304+ decode (Node v [] ) | mentions_itself v = NECyclicSCC (vertex_fn v :| [] )
262305 | otherwise = AcyclicSCC (vertex_fn v)
263- decode other = CyclicSCC (dec other [] )
264- where
265- dec (Node v ts) vs = vertex_fn v : foldr dec vs ts
306+ decode ( Node v ts) = NECyclicSCC (vertex_fn v :| foldr dec [] ts )
307+
308+ dec (Node v ts) vs = vertex_fn v : foldr dec vs ts
266309 mentions_itself v = v `elem` (graph ! v)
267310{-# INLINABLE stronglyConnCompR #-}
268311
0 commit comments