Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# constructor doesn't accept tuples?

I tried to use a tuple to create a new instance of a class defined in F#. To duplicate the problem, I tried the following code.

type test(x: int, y:int) =
    let distance =
        x * x + y * y |> float |> sqrt
    new (x: int, y:int, z:int) =
        new test(x, y)
let args = 1, 2
let test2 = new test(args)

It complains that

Error 1 The member or object constructor 'test' does not take 1 argument(s). An overload was found taking 2 arguments.

If I remove the non-default constructor, things are fine. I don't understand why it becomes two/three arguments instead of tuples.

Thank you very much.

like image 628
LLS Avatar asked Jul 09 '11 18:07

LLS


2 Answers

There may be an easier syntax to get this working, but I don't know what it is:

type Test(tup : int*int) =
    let x, y = tup
    let distance =
        x * x + y * y |> float |> sqrt
    new (tup : int*int*int) =
        let x, y, _ = tup
        new Test((x, y))

let args1 = 1, 2
let test1 = new Test(args1)

let args2 = 3, 4, 5
let test2 = new Test(args2)
like image 68
ildjarn Avatar answered Oct 19 '22 02:10

ildjarn


This is subtle, but per the spec. Here's an old email response I dug up where someone asked a similar question:

...

At play, there is also (subtle) difference between "tuples" (in the F# language) and "syntactic tuples" (in the F# specification).

Method application resolution is different when there are overloads. If there are none, the decomposition of the argument (i.e. the "stuff" specified between ( and ) in your method invocation) to a tuple form does not happen, so the compiler is happy and say "oh ok, the ctor for MyClass takes 1 argument (a tuple) and I am seeing 1 argument ("tuple" in your code) so I’ll use that".

Whereas, when you have 2 overloads, then the rule above does not apply anymore and the compiler will try to decompose the argument to a tuple form (which in your case would resolve in something like: "Oh ok, there is 1 argument which is tuple. But wait, I have 2 overloads. And your list of argument (one element, tuple) does not match either an argument list, hence the error message"

At least, that’s my interpretation of the F# specification, section 14.4.

like image 23
Brian Avatar answered Oct 19 '22 03:10

Brian