trans env (Case e alts) = do
  (dv, e') <- trans env e
  actualTypes <- fmap reverse (getActualTypes dv)
  let arity = length actualTypes

  (altTypeList, e2List) <- mapAndUnzipM (transPattern dv actualTypes) alts
  unless (all (alphaEq . head $ altTypeList) (tail altTypeList)) $ throwError "Bad pattern expressions"

  let (Pi "" _ t) = head . filter (\(Pi "" _ t') -> t' /= Error) $ altTypeList
  let genExpr = foldl App (App (U (arity + 1) e') t) e2List

  return (t, genExpr)

  where
    transPattern :: Type -> [Type] -> Alt -> TC (Type, Expr)
    transPattern dv tys (Alt (PConstr constr params) body) = do
      let k = constrName constr
      (kt, _) <- trans env (Var k)

      -- check patterns, quite hacky
      let tcApp = foldl App (Var "dummy$") (tys ++ map (Var . fst) params)
      (typ, _) <- trans (("dummy$", kt) : params ++ env) tcApp
      unless (alphaEq typ dv) $ throwError "Bad patterns"

      (bodyType, body') <- trans (params ++ env) body

      return (arr dv bodyType, genLambdas params body')
trans env (Case e alts) = do
  (dv, e') <- trans env e
  actualTypes <- fmap reverse (getActualTypes dv)
  let arity = length actualTypes

  (altTypeList, e2List) <- mapAndUnzipM (transPattern dv actualTypes) alts
  unless (all (alphaEq . head $ altTypeList) (tail altTypeList)) $ throwError "Bad pattern expressions"

  let (Pi "" _ t) = head . filter (\(Pi "" _ t') -> t' /= Error) $ altTypeList
  let genExpr = foldl App (App (U (arity + 1) e') t) e2List

  return (t, genExpr)

  where
    transPattern :: Type -> [Type] -> Alt -> TC (Type, Expr)
    transPattern dv tys (Alt (PConstr constr params) body) = do
      let k = constrName constr
      (kt, _) <- trans env (Var k)

      -- check patterns, quite hacky
      let tcApp = foldl App (Var "dummy$") (tys ++ map (Var . fst) params)
      (typ, _) <- trans (("dummy$", kt) : params ++ env) tcApp
      unless (alphaEq typ dv) $ throwError "Bad patterns"

      (bodyType, body') <- trans (params ++ env) body

      return (arr dv bodyType, genLambdas params body')
trans env (Case e alts) = do
  (dv, e') <- trans env e
  actualTypes <- fmap reverse (getActualTypes dv)
  let arity = length actualTypes

  (altTypeList, e2List) <- mapAndUnzipM (transPattern dv actualTypes) alts
  unless (all (alphaEq . head $ altTypeList) (tail altTypeList)) $ throwError "Bad pattern expressions"

  let (Pi "" _ t) = head . filter (\(Pi "" _ t') -> t' /= Error) $ altTypeList
  let genExpr = foldl App (App (U (arity + 1) e') t) e2List

  return (t, genExpr)

  where
    transPattern :: Type -> [Type] -> Alt -> TC (Type, Expr)
    transPattern dv tys (Alt (PConstr constr params) body) = do
      let k = constrName constr
      (kt, _) <- trans env (Var k)

      -- check patterns, quite hacky
      let tcApp = foldl App (Var "dummy$") (tys ++ map (Var . fst) params)
      (typ, _) <- trans (("dummy$", kt) : params ++ env) tcApp
      unless (alphaEq typ dv) $ throwError "Bad patterns"

      (bodyType, body') <- trans (params ++ env) body

      return (arr dv bodyType, genLambdas params body')