Я думаю, что вы используете слово «свободно» здесь - и это не вина против вас. Я сомневаюсь, что кто-то в здравом уме собирается использовать ссылки в своей рекурсивной структуре данных; и будучи новичком, мне трудно оправдать, что вы подразумеваете это буквально как таковое.
Есть разница, потому что в функциональных языках мы обычно имеем дело с неизменяемыми структурами данных. Я думаю, что вы хотите спросить, как вернуть новую структуру с указанным тегом, замененным другим. Помимо педантизма, это очень естественно делать на функциональных языках, и это будет то, что вы будете рассматривать редко.
Позволяет полностью определить структуру, с которой вы работаете. Я дополнительно определил тег - я предполагаю, что это строка.
type tag = string
type xml = Element of tag * xml list | CharData of string;;
И подпись для функции (поэтому мы понимаем, что мы пытаемся выполнить),
val replace_tag : string -> string -> xml -> xml
let rec replace_tag from_tag to_tag = function
(* nothing to do here... *)
| (CharData _ ) as x -> x
(* an element with the proper tag; call function on its contents *)
| Element (tag, xmlist) when tag = tag_from ->
let xmlist = List.map (fun t -> replace_tag from_tag to_tag t) xmlist in
let ntag,ncontent = f tag xmlist in
Element (tag_to,xmlist)
(* look into each element of xml contents *)
| Element (tag, xmlist) ->
let xmlist = List.map (fun t -> replace_tag from_tag to_tag t) xmlist in
Element(tag,xmlist)
Это приличное, простое решение того, что я думаю о вашей проблеме. Есть ряд проблем с этим, хотя; он не выполняет проверку ошибок, если значение не существует, и каждый раз копирует всю структуру данных - из-за вызова List.map
. С некоторыми подробностями, я думаю, мы сможем предложить вам лучшее решение.