trans env (Data db@(DB tc tca constrs) e) = do
  env' <- tcdatatypes env db
  let nenv = env' ++ env
  (t, e') <- trans nenv e

  let tct = mkProdType (Kind Star) tca
  let du = foldl App (Var tc) (map (Var . fst) tca)
  let dcArgs = map constrParams constrs
  let dcArgChains = map (mkProdType (Var "B0")) dcArgs
  let transTC' = map (mkProdType (Var "B0") . map (second (substVar tc "X"))) dcArgs
  let transTC = (tc, (tct, Mu "X" tct
                             (genLambdas tca (Pi "B0" (Kind Star) (chainType (Var "B0") transTC')))))

  let tduList = map (mkProdType du . constrParams) constrs
  let dctList = map (`mkProdType` tca) tduList

  let arity = length tca
  let transDC = zip (map constrName constrs)
                  (zip dctList
                     (map
                        (\(i, taus) ->
                           let cs = genVarsAndTypes 'c' dcArgChains
                           in genLambdas tca
                                (genLambdas taus
                                   (F (arity + 1) du
                                      (Lam "B0" (Kind Star)
                                         (genLambdas cs
                                            (foldl App (Var ('c' : show i)) (map (Var . fst) taus)))))))
                        (zip [0 :: Int ..] dcArgs)))
  return (t, foldr (\(n, (kt, ke)) body -> Let n kt ke body) e' (transTC : transDC))
trans env (Data db@(DB tc tca constrs) e) = do
  env' <- tcdatatypes env db
  let nenv = env' ++ env
  (t, e') <- trans nenv e

  let tct = mkProdType (Kind Star) tca
  let du = foldl App (Var tc) (map (Var . fst) tca)
  let dcArgs = map constrParams constrs
  let dcArgChains = map (mkProdType (Var "B0")) dcArgs
  let transTC' = map (mkProdType (Var "B0") . map (second (substVar tc "X"))) dcArgs
  let transTC = (tc, (tct, Mu "X" tct
                             (genLambdas tca (Pi "B0" (Kind Star) (chainType (Var "B0") transTC')))))

  let tduList = map (mkProdType du . constrParams) constrs
  let dctList = map (`mkProdType` tca) tduList

  let arity = length tca
  let transDC = zip (map constrName constrs)
                  (zip dctList
                     (map
                        (\(i, taus) ->
                           let cs = genVarsAndTypes 'c' dcArgChains
                           in genLambdas tca
                                (genLambdas taus
                                   (F (arity + 1) du
                                      (Lam "B0" (Kind Star)
                                         (genLambdas cs
                                            (foldl App (Var ('c' : show i)) (map (Var . fst) taus)))))))
                        (zip [0 :: Int ..] dcArgs)))
  return (t, foldr (\(n, (kt, ke)) body -> Let n kt ke body) e' (transTC : transDC))
trans env (Data db@(DB tc tca constrs) e) = do
  env' <- tcdatatypes env db
  let nenv = env' ++ env
  (t, e') <- trans nenv e

  let tct = mkProdType (Kind Star) tca
  let du = foldl App (Var tc) (map (Var . fst) tca)
  let dcArgs = map constrParams constrs
  let dcArgChains = map (mkProdType (Var "B0")) dcArgs
  let transTC' = map (mkProdType (Var "B0") . map (second (substVar tc "X"))) dcArgs
  let transTC = (tc, (tct, Mu "X" tct
                             (genLambdas tca (Pi "B0" (Kind Star) (chainType (Var "B0") transTC')))))

  let tduList = map (mkProdType du . constrParams) constrs
  let dctList = map (`mkProdType` tca) tduList

  let arity = length tca
  let transDC = zip (map constrName constrs)
                  (zip dctList
                     (map
                        (\(i, taus) ->
                           let cs = genVarsAndTypes 'c' dcArgChains
                           in genLambdas tca
                                (genLambdas taus
                                   (F (arity + 1) du
                                      (Lam "B0" (Kind Star)
                                         (genLambdas cs
                                            (foldl App (Var ('c' : show i)) (map (Var . fst) taus)))))))
                        (zip [0 :: Int ..] dcArgs)))
  return (t, foldr (\(n, (kt, ke)) body -> Let n kt ke body) e' (transTC : transDC))