views:

228

answers:

3
+1  Q: 

Ocaml Syntax Error

I'm using an implementation of lazy lists where the type can be either Nil or Cons (value, thunk), where thunk is a function from unit to the rest of the list.

I'm trying to write a function cross, which would function as List.combine does. Unfortunately, I'm having syntax errors.

open Sequence;;
    let rec (cross : 'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t) = match seq1 with
        Nil -> match seq2 with
            Cons (value2, thunk2) -> Cons ((Nil, value2), function () -> (cross Nil (thunk2 ())))
      | Cons (value1, thunk1) -> match seq2 with
            Nil -> Cons ((value1, Nil), function() -> (cross Nil (thunk1 ())))
          | Cons (value2, thunk2) -> Cons ((value1, value2), function() -> (cross (thunk1 ()) (thunk2 ())))

This produces the error:

Error: Unbound value seq1

what am I doing wrong?

UPDATE:

This type checks, but is not of the type I'm looking for.

let rec cross (seq1 : 'a Sequence.t) (seq2 : 'b Sequence.t) : ('a * 'b) Sequence.t = match seq1 with
    Nil -> match seq2 with
        Cons (value2, thunk2) -> Cons ((Nil, value2), function () -> (cross Nil (thunk2 ())))
  | Cons (value1, thunk1) -> match seq2 with
        Nil -> Cons ((value1, Nil), function() -> (cross Nil (thunk1 ())))
      | Cons (value2, thunk2) -> Cons ((value1, value2), function() -> (cross (thunk1 ()) (thunk2 ())))

val cross :
  'a Sequence.t Sequence.t ->
  'a Sequence.t Sequence.t -> ('a Sequence.t * 'a Sequence.t) Sequence.t =
  <fun>

This is not the type of cross that I want. I'm looking for:

'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t
+3  A: 

you are going to kick yourself... where is seq1 defined?

let rec (cross : 'a Sequence.t -> 'b Sequence.t -> ('a * 'b) Sequence.t) =

You define the type of cross, but you don't bind the variables to anything (I guess, you can say that).

let rec cross (seq1:'a Sequence.t) (seq2:'a Sequence.t) :('a * 'b) Sequence.t =

EDIT:

I think your matching is well, mis-matched. Use begin ... end blocks around the cases, I think what is happening (and since I don't have Sequence, I cannot verify) is that the match cases you intend for the outer match are being applied to the inner one, matching seq2. for example,

match x with
| 0 -> match y with
    | 1 -> "x:0, y:1"
| 2 -> match y with
    | 0 -> "y:0, x:2"

Although, spatially, it looks fine, the second match, match y with is bound with the | 2 -> ... match case. Here is a version with the being ... end keywords surrounding the match cases. The second begin ... end isn't needed, but it's probably a good idea to do it anyway for clarity.

match x with 
| 0 -> begin match y with
    | 1 -> "x:0, y:1" end
| 2 -> begin match y with
    | 0 -> "y:0, x:2" end
nlucaroni
yes, that is correct. but now I'm having another issue.
Rosarch
+1: I got +1 while my answer was more recent (by a couple of seconds but still...).
LB
+2  A: 

in the first line, you're trying to match against seq1, but this value is unbound meaning that it's nowhere to be found.

That's exactly the same as :

# let t =
  match t1 with
  _ -> ();;
Error: Unbound value t1

You have to name your arguments.

LB
+2  A: 

For your updated question, the reason the types are 'a Sequence.t Sequence.t is because of the line

Cons ((Nil, value2), ...)

Recall that Nil is a sequence itself, so by putting that there it forces all the elements of the input sequences to be sequences too.

newacct
ok, so then how do I express ('a * 'b) without making both elements sequences?
Rosarch
@Rosarch: Well, I dunno; because there is no obvious way to express an "empty" value. Let me ask you this: suppose you wanted to write this function for regular lists, i.e. you wanted to make a function that is " 'a list -> 'b list -> ('a * 'b) list ". How would you do it? How would you handle lists of different lengths?
newacct
@newacct +1 : List.combine does not handle lists of different lengths, you've got an InvalidArgument. I don't really know what you can do since there's no empty value. That's a good point. :-)
LB