varsToHoles :: forall f v. (HTraversable f, HasVars f v, Ord v) =>
                Term f :-> Context f (K v)
varsToHoles t = unC (cata alg t) Set.empty
    where alg :: (HTraversable f, HasVars f v, Ord v) => Alg f (C (Set v) (Context f (K v)))
          alg t = C $ \vars -> case isVar t of
            Just v | not (v `Set.member` vars) -> Hole $ K v
            _  -> Term $ hfmapBoundVars run t
              where
                run :: Set v -> C (Set v) (Context f (K v))  :-> Context f (K v)
                run newVars f = f `unC` (newVars `Set.union` vars)

-- | Convert variables to holes, except those that are bound.
varsToHoles :: forall f v. (HTraversable f, HasVars f v, Ord v) =>
                Term f :-> Context f (K v)
varsToHoles t = unC (cata alg t) Set.empty
    where alg :: (HTraversable f, HasVars f v, Ord v) => Alg f (C (Set v) (Context f (K v)))
          alg t = C $ \vars -> case isVar t of
            Just v | not (v `Set.member` vars) -> Hole $ K v
            _  -> Term $ hfmapBoundVars run t
              where
                run :: Set v -> C (Set v) (Context f (K v))  :-> Context f (K v)
                run newVars f = f `unC` (newVars `Set.union` vars)

-- | Convert variables to holes, except those that are bound.
varsToHoles t = unC (cata alg t) Set.empty
    where alg :: (HTraversable f, HasVars f v, Ord v) => Alg f (C (Set v) (Context f (K v)))
          alg t = C $ \vars -> case isVar t of
            Just v | not (v `Set.member` vars) -> Hole $ K v
            _  -> Term $ hfmapBoundVars run t
              where
                run :: Set v -> C (Set v) (Context f (K v))  :-> Context f (K v)
                run newVars f = f `unC` (newVars `Set.union` vars)

-- | Convert variables to holes, except those that are bound.