let rec infer env t = 
  match t with
      TypVar (p, id) -> 
        lookup id env

    | TypApp (p, tc, ts) ->
        let k = variable () in
        let kd = 
          List.fold_right (fun t acu -> mkarrow (infer env t) acu) 
            ts k 
            
        in
          unify p (infer env tc) kd; 
          k

    | TypRowCons (p, attributes, t) ->
        List.iter (fun (_,ta) -> check p env ta star) attributes;
        let defined_labels = 
          List.fold_left 
            (fun acu (LName l,_) -> 
               if IdSet.mem l acu then raise (MultipleLabels (p, LName l))
               else IdSet.add l acu) 
            IdSet.empty 
            attributes in
        let domain = RowDomain.svariable () in
          check p env t (row (RowDomain.sum defined_labels domain));
          row domain

    | TypRowUniform (p, typ) ->
        row (RowDomain.svariable ())
          
and check pos env t k = 
  unify pos (infer env t) k