简体   繁体   中英

Folding over Trees in OCaml

This is my attempt of implementing fold (left) for the tree (it is very simplified version, but carefully reproduces real tree structure):

type 'a tree = Leaf of 'a | Node of 'a * 'a tree list

let rec fold t acc f =
  match t with
  | Leaf x -> f acc x None
  | Node (x, lst) ->
    let deferred acc =
      List.fold_left (fun acc t' -> fold t' acc f) acc lst in
    f acc x (Some deferred)

The idea is to use deferred call for subtrees. It lets us:

  • skip a subtree traversing if needed
  • initialize a subtree traversing and compose results

A toy example:

open Printf

let () =
  let tree = Node (3, [Leaf 5; Leaf 3; Node (11, [Leaf 1; Leaf 2]); Leaf 18]) in

  fold tree "" (fun str x nested ->
      let plus str = if String.length str = 0 then "" else "+" in
      let x = string_of_int x in
      match nested with
      | None -> str ^ (plus str) ^ x
      | Some f -> str ^ (plus str) ^ x ^ "*(" ^ (f "") ^ ")"
    )
  |> printf "%s=";

  fold tree 0 (fun acc x -> function
      | None -> acc + x
      | Some f -> x * (f 0) + acc
    )
  |> printf "%d\n";

I guess this was invented many times already. Is there any name for this technique? Any well-known canonic form? Any ideas how to make it better?

A more canonical will be to define a lazy data structure. Possibly like this:

type 'a tree = unit -> 'a tr
and 'a tr = Stem of 'a * 'a tree list

Or, you can try OCaml's lazy values.

Trying to lazily traverse a non-lazy data structure is not very canonic, IMO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM