+-- A monad holding a set of vertices visited so far.
+#if USE_ST_MONAD
+
+-- Use the ST monad if available, for constant-time primitives.
+
+newtype SetM s a = SetM { runSetM :: STArray s Vertex Bool -> ST s a }
+
+instance Monad (SetM s) where
+ return x = SetM $ const (return x)
+ SetM v >>= f = SetM $ \ s -> do { x <- v s; runSetM (f x) s }
+
+run :: Bounds -> (forall s. SetM s a) -> a
+run bnds act = runST (newArray bnds False >>= runSetM act)
+
+contains :: Vertex -> SetM s Bool
+contains v = SetM $ \ m -> readArray m v
+
+include :: Vertex -> SetM s ()
+include v = SetM $ \ m -> writeArray m v True
+
+#else /* !USE_ST_MONAD */
+
+-- Portable implementation using IntSet.
+
+newtype SetM s a = SetM { runSetM :: IntSet -> (a, IntSet) }
+
+instance Monad (SetM s) where
+ return x = SetM $ \ s -> (x, s)
+ SetM v >>= f = SetM $ \ s -> case v s of (x, s') -> runSetM (f x) s'
+
+run :: Bounds -> SetM s a -> a
+run _ act = fst (runSetM act Set.empty)
+
+contains :: Vertex -> SetM s Bool
+contains v = SetM $ \ m -> (Set.member v m, m)
+
+include :: Vertex -> SetM s ()
+include v = SetM $ \ m -> ((), Set.insert v m)
+
+#endif /* !USE_ST_MONAD */
+