Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 714
Stas Avatar asked Mar 26 '14 08:03

Stas


1 Answers

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.

like image 160
ivg Avatar answered Sep 23 '22 19:09

ivg