2

I have two types:

type 'a llist = 
      LNil 
    | LCons of 'a * (unit -> 'a llist);;

type 'a lBT = 
      LEmpty 
    | LNode of 'a * (unit -> 'a lBT) * (unit -> 'a lBT);;

I need to write function that gets lazy list and returns lazy BST. I currently have two functions, first (add, which gets element and a tree and returns a tree with this element) seems ok, but with the second one (which iterates through list and creates a new tree adding all the elements from list) I get error. For me it looks ok, but I probably just don't understand something. And I have no idea what.

let rec add (elem, tree) = 
    match (elem, tree) with
      (None, _) -> LEmpty
        | (x, LEmpty) -> LNode (x, (function() -> add (None, LEmpty)), (function() -> add (None, LEmpty)))
        | (x, LNode (y, l, r)) when x < y -> LNode(y, (function () -> add (x, l())), r)
        | (x, LNode (y, l, r)) -> LNode(y, l, (function () -> add (x, r())));;

let toLBST listal = 
    let rec toLBST_rec listal tree =
        match listal with
          LNil -> tree
            | LCons(x, xs) -> toLBST_rec (xs()) add(x, tree)
    in toLBST_rec (listal, LEmpty);;

I get:

Characters 141-145:
    | LCons(x, xs) -> toLBST_rec (xs()) add(x, tree)
                                               ^^^^
Error: This expression has type 'a option * 'a option lBT -> 'a option lBT
    but an expression was expected of type 'a option lBT

I have no idea what should I do, for it to work properly. I tried a few things but every time I get some error.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
ajgoralczyk
  • 35
  • 1
  • 10
  • in `add`, instead of `(None, _) -> LEmpty` it should be `(Nil, _) -> tree`. -- as gasche said, either have a definition with pair, `let rec fun (a,b) = ... in fun (x,y)` or with two arguments, `let rec fun a b = ... in fun (x) (y)`, but the call and the definition should be consistent. – Will Ness Jan 25 '14 at 14:49

1 Answers1

2

Here are the various mistakes you made in your code:

  (None, _) -> LEmpty

This is wrong, there is no reason for elem to be an option type. In the LEmpty case, simply use LEmpty to define the children of the lazy tree returned.

        | LCons(x, xs) -> toLBST_rec (xs()) add(x, tree)

You forgot parentheses around add(x, tree).

in toLBST_rec (listal, LEmpty);;

You defined toLBST_rec to take two parameters, now you're passing it only one, of the wrong type (a pair of a list and a tree ,while the parameter expects only a list). You seem to be confused about the syntax of multi-parameter (currified) functions in OCaml. You should avoid (.. , ..) in function declarations and calls, and define instead let rec add elem tree =, etc.

gasche
  • 31,259
  • 3
  • 78
  • 100
  • the output lazy tree may be allowed to be out of balance, so its root need not be a median value - it can just be the list's head. Yes, in- and post-order will have to force the whole tree at once, but pre-order and breadth-first won't necessarily force out the whole tree at once. – Will Ness Jan 25 '14 at 14:36
  • you are correct; in that case a simple quicksort will do the job: take the first element to be the pivot, and then define the left and right children as the traduction of the (lazy) partitioning of the rest of the list. – gasche Jan 25 '14 at 17:07
  • after giving it a tad more thought, the quicksort sketched above should be equivalent to the lazy folding of the `add` function above, so there is not reason to change the algorithmics. Nice! I removed my paragraph about mis-understanding the choice of lazyness, thanks. – gasche Jan 25 '14 at 17:12
  • yes, the lazy folding of `add` over the input lazy list is what `toLBST` should be; then for *lazy* partitioning we have to carefully use a pre-order traversal, or a breadth-first traversal, of both branches. When the left-most node of the tree (the smallest element in the list) is reached, the input list will be fully consumed at that point, but the tree won't yet be fully formed. With pre-order we're lazier with tree-building, and with breadth-first we're lazier with list-consuming. Nice, how the added freedom comes with a non-orderedness of the two parts of the partition. :) – Will Ness Jan 25 '14 at 17:48
  • come to think of it, the in- or post-order will only fully force the *list* when the head of the resulting list is demanded, but the tree won't be fully formed yet, either. – Will Ness Jan 25 '14 at 19:41