If you want to expose some fields but not others, you can declare abstract types for the private fields. Inside the module this type is just an alias to the actual type, but outside, it makes the field totally unusable.
E.g
type generative_id (* can't do anything *)
type ast = {
view: ast_view;
ty : type_;
id: generative_id; (* effectively private *)
}
and ast_view = Add of ast * ast | …
and type_ = …
edit: an additional benefit is that you can pattern-match on such records.