Конструктор F # не принимает кортежи?

Я попытался использовать кортеж для создания нового экземпляра класса, определенного в F#. Чтобы воспроизвести проблему, я попробовал следующий код.

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)

Он жалуется, что

Ошибка 1 Конструктор члена или объекта 'test' не принимает 1 аргумент(ы). Обнаружена перегрузка, принимающая 2 аргумента.

Если я удалю конструктор не по умолчанию, все будет в порядке. Я не понимаю, почему это становится двумя/тремя аргументами вместо кортежей.

Большое Вам спасибо.


person LLS    schedule 09.07.2011    source источник


Ответы (2)


Это тонко, но согласно спецификации. Вот старый ответ по электронной почте, который я откопал, где кто-то задавал аналогичный вопрос:

...

В игре также есть (тонкая) разница между «кортежами» (в языке F#) и «синтаксическими кортежами» (в спецификации F#).

Разрешение приложения метода отличается при наличии перегрузок. Если их нет, разложения аргумента (т. е. «материала», указанного между ( и ) в вызове вашего метода) в форму кортежа не происходит, поэтому компилятор доволен и говорит: «О, хорошо, ctor для MyClass принимает 1 аргумент (кортеж), и я вижу 1 аргумент ("кортеж" в вашем коде), поэтому я буду использовать его".

Принимая во внимание, что когда у вас есть 2 перегрузки, то вышеприведенное правило больше не применяется, и компилятор попытается разложить аргумент в виде кортежа (который в вашем случае разрешится примерно так: «О, хорошо, есть 1 аргумент, который кортеж. Но подождите, у меня есть 2 перегрузки. И ваш список аргументов (один элемент, кортеж) не соответствует ни одному списку аргументов, отсюда и сообщение об ошибке"

По крайней мере, это моя интерпретация спецификации F#, раздел 14.4.

person Brian    schedule 09.07.2011
comment
Я не был удивлен, что компилятор не рассматривает аргумент конструктора как кортеж в этом случае, но я был очень удивлен, что вы не можете использовать шаблоны в привязке конструктора, т.е. type Test( (x, y) ) = ... (или любые другие шаблоны). Есть ли причина для этого? - person Tomas Petricek; 10.07.2011
comment
Большое спасибо. F# действительно сбивает с толку в некоторых аспектах. - person LLS; 10.07.2011
comment
Я был тем, кто спросил по электронной почте; рад, что я не единственный, кто нашел это запутанным! Вы также получите ту же проблему, используя перегрузку метода (конструктор рассматривается как метод). - person Samuel; 10.07.2011
comment
@Brian - я полагаю, это может быть связано с тем, что в данном случае аргументы конструктора становятся полями, поэтому стоит более подробно указать, как они определены. Но все же мне это кажется неправильным. - person Tomas Petricek; 11.07.2011

Для этого может быть более простой синтаксис, но я не знаю, что это такое:

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)
person ildjarn    schedule 09.07.2011
comment
Спасибо. Я думал, что несколько аргументов в паре скобок — это то же самое, что и кортежи. - person LLS; 10.07.2011