synthExpr _ gam _ (Val s _ (Constr _ c [])) = do
  -- Should be provided in the type checkers environment
  st <- get
  mConstructor <- lookupDataConstructor s c
  case mConstructor of
    Just (tySch, coercions) -> do
      -- Freshen the constructor
      -- (discarding any fresh type variables, info not needed here)

      (ty, _, _, constraints, coercions') <- freshPolymorphicInstance InstanceQ False tySch coercions

      mapM_ (\ty -> do
        pred <- compileTypeConstraintToConstraint s ty
        addPredicate pred) constraints

      -- Apply coercions
      ty <- substitute coercions' ty

      let elaborated = Val s ty (Constr ty c [])
      return (ty, [], [], elaborated)

    Nothing -> throw UnboundDataConstructor{ errLoc = s, errId = c }

-- Case synthesis
synthExpr _ gam _ (Val s _ (Constr _ c [])) = do
  -- Should be provided in the type checkers environment
  st <- get
  mConstructor <- lookupDataConstructor s c
  case mConstructor of
    Just (tySch, coercions) -> do
      -- Freshen the constructor
      -- (discarding any fresh type variables, info not needed here)

      (ty, _, _, constraints, coercions') <- freshPolymorphicInstance InstanceQ False tySch coercions

      mapM_ (\ty -> do
        pred <- compileTypeConstraintToConstraint s ty
        addPredicate pred) constraints

      -- Apply coercions
      ty <- substitute coercions' ty

      let elaborated = Val s ty (Constr ty c [])
      return (ty, [], [], elaborated)

    Nothing -> throw UnboundDataConstructor{ errLoc = s, errId = c }

-- Case synthesis
synthExpr _ gam _ (Val s _ (Constr _ c [])) = do
  -- Should be provided in the type checkers environment
  st <- get
  mConstructor <- lookupDataConstructor s c
  case mConstructor of
    Just (tySch, coercions) -> do
      -- Freshen the constructor
      -- (discarding any fresh type variables, info not needed here)

      (ty, _, _, constraints, coercions') <- freshPolymorphicInstance InstanceQ False tySch coercions

      mapM_ (\ty -> do
        pred <- compileTypeConstraintToConstraint s ty
        addPredicate pred) constraints

      -- Apply coercions
      ty <- substitute coercions' ty

      let elaborated = Val s ty (Constr ty c [])
      return (ty, [], [], elaborated)

    Nothing -> throw UnboundDataConstructor{ errLoc = s, errId = c }

-- Case synthesis