{- Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. -} module Glean.Util.TransitiveClosure ( transitiveClosureBy ) where import Data.Foldable as Foldable import Data.Hashable import qualified Data.HashMap.Strict as HashMap transitiveClosureBy :: (Eq k, Hashable k, Foldable f) => (a -> k) -> (a -> f a) -> [a] -> [a] transitiveClosureBy k fn xs = HashMap.elems $ go xs HashMap.empty where go [] r = r go (n:ns) r | k n `HashMap.member` r = go ns r | otherwise = go (Foldable.toList (fn n) ++ ns) (HashMap.insert (k n) n r)