let init_env () = 
  let builtins = 
    init_builtin_env (fun ?name () -> variable Rigid ?name:name ())
  in

    (* Add the builtin data constructors into the environment. *)
  let init_ds adt_name acu ds = 
    if ds = [] then None, acu 
    else 
      let (env, acu, lrqs, let_env) as r = 
        List.fold_left 
          (fun acu (d, rqs, ty) -> 
             intern_data_constructor undefined_position adt_name acu 
               (undefined_position, d, rqs, ty)
          ) acu ds
      in
        (Some acu, r)
  in
    
    (* For each builtin algebraic datatype, define a type constructor
       and related data constructors into the environment. *)

  let (init_env, acu, lrqs, let_env) = 
    List.fold_left 
      (fun (env, dvs, lrqs, let_env) (n, (kind, v, ds)) -> 
           let r = ref None in
           let env = add_type_constructor env n 
             (MiniKindInferencer.intern_kind (as_kind_env env) kind,
              variable ~name:n Constant (),
              r) in
           let (dvs, acu) = init_ds n (env, dvs, lrqs, let_env) ds in
             r := dvs;
             acu
      )
      (empty_environment, [], [], StringMap.empty)
      (List.rev builtins)
  in
  let vs = 
    fold_type_info (fun vs (n, (_, v, _)) -> v :: vs) [] init_env
  in
    (* The initial environment is implemented as a constraint context. *)
    (fun c -> 
       CLet ([ Scheme (undefined_position, vs, [], 
                       CLet ([ Scheme (undefined_position, lrqs, [],
                                       CTrue undefined_position, 
                                       let_env) ],
                             c),
                       StringMap.empty) ], 
             CTrue undefined_position)),
  init_env