extractLoop :: IM.IntMap Int -> (IS.IntSet, IM.IntMap Int)
extractLoop m = case IM.minViewWithKey m of
    Nothing -> (IS.empty, m)
    Just ((k,_), _) ->
      let findLoop start cur acc =
            let next = m IM.! cur
            in if next == start
                then acc
                else findLoop start next (IS.insert cur acc)
          loop = findLoop k k (IS.singleton k)
      in (loop, cutClear (IM.withoutKeys m loop))
extractLoop :: IM.IntMap Int -> (IS.IntSet, IM.IntMap Int)
extractLoop m = case IM.minViewWithKey m of
    Nothing -> (IS.empty, m)
    Just ((k,_), _) ->
      let findLoop start cur acc =
            let next = m IM.! cur
            in if next == start
                then acc
                else findLoop start next (IS.insert cur acc)
          loop = findLoop k k (IS.singleton k)
      in (loop, cutClear (IM.withoutKeys m loop))
extractLoop m = case IM.minViewWithKey m of
    Nothing -> (IS.empty, m)
    Just ((k,_), _) ->
      let findLoop start cur acc =
            let next = m IM.! cur
            in if next == start
                then acc
                else findLoop start next (IS.insert cur acc)
          loop = findLoop k k (IS.singleton k)
      in (loop, cutClear (IM.withoutKeys m loop))