delete :: Eq a => Term f -> a -> Index f a -> Index f a
delete !t x !idx = aux (Term.singleton t) idx
  where
    aux _ Nil = Nil
    aux (ConsSym{rest = ts}) idx@Index{prefix = u@ConsSym{rest = us}} =
      -- The prefix must match, since the term ought to be in the index
      -- (which is checked in the Empty case below).
      case aux ts idx{prefix = us} of
        Nil -> Nil
        idx -> idx{prefix = u}
    aux _ idx@Index{prefix = Cons{}} = idx

    aux Empty idx
      | x `List.elem` here idx =
        idx { here = List.delete x (here idx) }
      | otherwise =
        error "deleted term not found in index"
    aux ConsSym{hd = App f _, rest = t} idx =
      idx { fun = update (fun_id f) (aux t (fun idx ! fun_id f)) (fun idx) }
    aux ConsSym{hd = Var _, rest = t} idx =
      idx { var = aux t (var idx) }

-- | Look up a term in the index. Finds all key-value such that the search term
-- is an instance of the key, and returns an instance of the the value which
-- makes the search term exactly equal to the key.

delete :: Eq a => Term f -> a -> Index f a -> Index f a
delete !t x !idx = aux (Term.singleton t) idx
  where
    aux _ Nil = Nil
    aux (ConsSym{rest = ts}) idx@Index{prefix = u@ConsSym{rest = us}} =
      -- The prefix must match, since the term ought to be in the index
      -- (which is checked in the Empty case below).
      case aux ts idx{prefix = us} of
        Nil -> Nil
        idx -> idx{prefix = u}
    aux _ idx@Index{prefix = Cons{}} = idx

    aux Empty idx
      | x `List.elem` here idx =
        idx { here = List.delete x (here idx) }
      | otherwise =
        error "deleted term not found in index"
    aux ConsSym{hd = App f _, rest = t} idx =
      idx { fun = update (fun_id f) (aux t (fun idx ! fun_id f)) (fun idx) }
    aux ConsSym{hd = Var _, rest = t} idx =
      idx { var = aux t (var idx) }

-- | Look up a term in the index. Finds all key-value such that the search term
-- is an instance of the key, and returns an instance of the the value which
-- makes the search term exactly equal to the key.

delete !t x !idx = aux (Term.singleton t) idx
  where
    aux _ Nil = Nil
    aux (ConsSym{rest = ts}) idx@Index{prefix = u@ConsSym{rest = us}} =
      -- The prefix must match, since the term ought to be in the index
      -- (which is checked in the Empty case below).
      case aux ts idx{prefix = us} of
        Nil -> Nil
        idx -> idx{prefix = u}
    aux _ idx@Index{prefix = Cons{}} = idx

    aux Empty idx
      | x `List.elem` here idx =
        idx { here = List.delete x (here idx) }
      | otherwise =
        error "deleted term not found in index"
    aux ConsSym{hd = App f _, rest = t} idx =
      idx { fun = update (fun_id f) (aux t (fun idx ! fun_id f)) (fun idx) }
    aux ConsSym{hd = Var _, rest = t} idx =
      idx { var = aux t (var idx) }

-- | Look up a term in the index. Finds all key-value such that the search term
-- is an instance of the key, and returns an instance of the the value which
-- makes the search term exactly equal to the key.
