1

I've got an F# assignment where I am trying to compute the transpose of a matrix. Simple enough, but I keep getting a value restriction error and I cannot figure out why. I consulted many of the VR error questions that are out there, but I'm still in the dark. Here's my code:

let transpose = function
    | [xs ; ys] -> 
                let rec transpose_helper = function
                    | [],[] -> []
                    | x::xs , y::ys -> [x;y] :: transpose_helper (xs,ys)
                    | _ -> failwith "The matrix is not a square matrix"
                transpose_helper(xs,ys)
    | _ -> failwith "Incorrectly formatted input"

transpose ([[1;2;3];[2;3;4]]);;

I assume the error is in part due to the empty list, but nothing I do seems to help. Any pointers would be greatly appreciated.

EDIT: This following version of the code, works. Could anyone explain why?

let transpose zs =
    match zs with 
    | [xs;ys] -> 
                let rec transpose_helper (xs, ys) = 
                    match (xs,ys) with
                    | ([],[]) -> []
                    | (x::xs , y::ys) -> [x;y] :: transpose_helper (xs,ys)
                    | _ -> failwith "The matrix is not a square matrix"
                transpose_helper(xs,ys)
    | _ -> failwith "Incorrectly formatted input"

transpose ([[1;2;3];[2;3;4]]);;

val transpose : zs:'a list list -> 'a list list
val it : int list list = [[1; 2]; [2; 3]; [3; 4]]

However, the compiler still complains that the transpose call above should have a unit type unless I bind it using lets. Could anyone please clarify what is going on here?

John Palmer
  • 25,356
  • 3
  • 48
  • 67
filpa
  • 3,651
  • 8
  • 52
  • 91

1 Answers1

5

My guess is you originally wrote this let rec transpose zs = match zs with ... and later changed it to use function instead, which removes the need for the explicit argument. Since zs is still there your function accepts two args which means you're only partially applying it. Since zs is unused its type is unknown making your partially applied function return a generic function value (value restriction). Remove zs and all is well.

Daniel
  • 47,404
  • 11
  • 101
  • 179
  • My apologies for the late comment: Unfortunately, that did not seem to solve the issue and the value restriction error remains. I've made the initial function non-recursive as I saw that it was not necessary, as well. Casting it (perhaps to an int list list) does not seem to work, either. – filpa Feb 11 '13 at 18:24
  • I've added a working version of the code with uses the match ... with ... pattern, but I am unsure of *why* it works in the first place when I still get a warning about types. I would greatly appreciate it if you could clarify! – filpa Feb 11 '13 at 18:31
  • 2
    After editing, both your `transpose` functions are equivalent and work. The latest error can be fixed by binding the result using `let` or piping to ignore (`|> ignore`). – Daniel Feb 11 '13 at 19:06