polyinstantiate
             :: forall m e c.
                ( Show c, Pretty c, FreshVarI m, CSL.ConstraintSetLike e c
                , CSL.ConstraintSetLikePromotable ConstraintSet c
                , Transform ReplaceVariables c)
             => UID -- ^The span at which this polyinstantiation occurred.
             -> QuantType c -- ^The type to polyinstantiate.
             -> m (QVar, c) -- ^The result of polyinstantiation.
polyinstantiate inst qt@(QuantType boundSet qa cs) = do
  _debug $ boxToString $
    ["Polyinstantiating quantified type: "] %+ prettyLines qt
  (qvarMap,uvarMap) <- mconcat <$> mapM freshMap (Set.toList boundSet)
  let (qa',cs') = replaceVariables qvarMap uvarMap (qa,cs)
  let cs'' = cs' `CSL.union` CSL.promote
               (csFromList (map (uncurry PolyinstantiationLineageConstraint)
                               $ Map.toList qvarMap))
  _debug $ boxToString $
    ["Polyinstantiated "] %+ prettyLines qt %$
      indent 2 (["to: "] %+ prettyLines qa' %+ ["\\"] %+ prettyLines cs'')
  return (qa',cs'')
  where
    freshMap :: AnyTVar -> m (Map QVar QVar, Map UVar UVar)
    freshMap var =
      case var of
        SomeQVar qa' -> do
          qa'' <- freshQVar $ TVarPolyinstantiationOrigin qa' inst
          return (Map.singleton qa' qa'', Map.empty)
        SomeUVar a' -> do
          a'' <- freshUVar $ TVarPolyinstantiationOrigin a' inst
          return (Map.empty, Map.singleton a' a'')
polyinstantiate
             :: forall m e c.
                ( Show c, Pretty c, FreshVarI m, CSL.ConstraintSetLike e c
                , CSL.ConstraintSetLikePromotable ConstraintSet c
                , Transform ReplaceVariables c)
             => UID -- ^The span at which this polyinstantiation occurred.
             -> QuantType c -- ^The type to polyinstantiate.
             -> m (QVar, c)
polyinstantiate inst qt@(QuantType boundSet qa cs) = do
  _debug $ boxToString $
    ["Polyinstantiating quantified type: "] %+ prettyLines qt
  (qvarMap,uvarMap) <- mconcat <$> mapM freshMap (Set.toList boundSet)
  let (qa',cs') = replaceVariables qvarMap uvarMap (qa,cs)
  let cs'' = cs' `CSL.union` CSL.promote
               (csFromList (map (uncurry PolyinstantiationLineageConstraint)
                               $ Map.toList qvarMap))
  _debug $ boxToString $
    ["Polyinstantiated "] %+ prettyLines qt %$
      indent 2 (["to: "] %+ prettyLines qa' %+ ["\\"] %+ prettyLines cs'')
  return (qa',cs'')
  where
    freshMap :: AnyTVar -> m (Map QVar QVar, Map UVar UVar)
    freshMap var =
      case var of
        SomeQVar qa' -> do
          qa'' <- freshQVar $ TVarPolyinstantiationOrigin qa' inst
          return (Map.singleton qa' qa'', Map.empty)
        SomeUVar a' -> do
          a'' <- freshUVar $ TVarPolyinstantiationOrigin a' inst
          return (Map.empty, Map.singleton a' a'')
polyinstantiate inst qt@(QuantType boundSet qa cs) = do
  _debug $ boxToString $
    ["Polyinstantiating quantified type: "] %+ prettyLines qt
  (qvarMap,uvarMap) <- mconcat <$> mapM freshMap (Set.toList boundSet)
  let (qa',cs') = replaceVariables qvarMap uvarMap (qa,cs)
  let cs'' = cs' `CSL.union` CSL.promote
               (csFromList (map (uncurry PolyinstantiationLineageConstraint)
                               $ Map.toList qvarMap))
  _debug $ boxToString $
    ["Polyinstantiated "] %+ prettyLines qt %$
      indent 2 (["to: "] %+ prettyLines qa' %+ ["\\"] %+ prettyLines cs'')
  return (qa',cs'')
  where
    freshMap :: AnyTVar -> m (Map QVar QVar, Map UVar UVar)
    freshMap var =
      case var of
        SomeQVar qa' -> do
          qa'' <- freshQVar $ TVarPolyinstantiationOrigin qa' inst
          return (Map.singleton qa' qa'', Map.empty)
        SomeUVar a' -> do
          a'' <- freshUVar $ TVarPolyinstantiationOrigin a' inst
          return (Map.empty, Map.singleton a' a'')