import Data.Set (Set, (\\)) import Data.Set qualified as S closure :: Ord a => (a -> [a]) -> Set a -> Set a closure f s = go S.empty s where go old new | null new = old | otherwise = go old' new' where old' = old <> new new' = S.fromList (concatMap f new) `S.difference` old' closure' :: Ord a => (a -> [a]) -> Set a -> Set a closure' f s = go f (S.toList s) s where go f xs s = let xs' = concatMap f xs s' = S.union s (S.fromList xs') in if S.size s == S.size s' then s else go f (S.toList (S.difference s' s)) s' g = ((:[]) . (`div` 2)) main :: IO () main = do print $ closure g (S.singleton 512) print $ closure' g (S.singleton 512)