Почему типы записей обязывают вас определять типы членов? - PullRequest
1 голос
/ 25 августа 2011

Кажется, что типы записей обязывают вас объявлять типы членов:

type Point = { X:int; Y:int }

Каково (или может быть) обоснование этого?

Кажется, что в F # вы можете (почти) всегда уходит без необходимости определять типы при кодировании.Это заставляет меня думать, что, возможно, существует сильная теоретическая база для этого ограничения.Это тот случай?

Ответ Роберту:

Я понимаю вашу точку зрения, но мне кажется, что рассуждения ошибочны.Давайте рассмотрим пример:

Давайте предположим, что F # позволяет нам определять элементы без типа:

type Point = { X; Y; }

Ваши рассуждения основаны на том факте, что это будет так, и можно найти вещи следующим образомв нашем коде:

let a = { X=1; y=2 } //(1)
let b = { X="1"; y="2" } //(2)

В этом случае у компилятора не будет выбора, кроме как определить (неявно) Point как

type Point = { X:object; Y:object }

Теперь вы, вероятно,не только создавать записи, но и использовать их.С учетом вышесказанного, возможно, в вашем коде будет место, где вы попытаетесь трактовать членов Point как целые числа:

let z = a.X + 2 //ERROR. goes against what is seen in (2)

и другие, где вы будете рассматривать их как строки:

let w = A.X + "abc" //ERROR. goes against what is seen in (1)

Оба будут отмечать ошибки, поэтому даже если вы попытаетесь использовать взаимно несовместимые типы для членов записей, вы не сможете!Будут ли они каким-либо образом совместимы, и F # найдет для нас наименее возможный тип root для использования.

Здесь есть разумное замечание, что в отличие от того, что вы описываете

* 1032Вы когда-нибудь хотели, чтобы поле внезапно меняло свой тип при переходе от одной записи к другой?

типы записей не будут менять при переходе от одной записи к другой.В худшем случае может случиться так, что типы членов Record будут довольно общими (в худшем случае из типа Object).

Но это тот же риск, который вы берете на себя, когда пишете метод, который принимает только аргументы без типов!И это, как мы знаем, разрешено в F #.

Итак, если я не пропустил что-то здесь, вероятно, это не причина, по которой у вас есть для определения типов в записях.

Ответы [ 2 ]

7 голосов
/ 25 августа 2011

Если бы F # позволял вам определять записи без типов, он, скорее всего, интерпретировал бы их как записи с универсальными типами полей (в отличие от использования object, как вы делали при редактировании).Итак, предположим, что:

type Point = { X; Y }

На самом деле означает:

type Point<'T1, 'T2> = { X : 'T1; Y : 'T2 }

Теперь вы можете написать { X = 1; Y = 2 }, а также { X = "foo"; Y = new System.Random() }.Однако это только делает записи менее полезными .Записи должны задокументировать значение значения двумя способами: 1) путем маркировки полей и 2) путем указания типов полей.Используя предложенную вами функцию, вы удалите (2).

Конечно, если у вас есть общая запись, вы все равно можете явно определить ее как таковую (и использовать ее с другими значениями), но сделав этоавтоматически, вероятно, не очень поможет.

1 голос
/ 25 августа 2011

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

Но это тот же риск, который вы берете на себя, когда пишете метод это принимает только аргументы без типа! И это, как мы знаем, разрешено в F #.

Нет функции с типом меньше параметров. Каждый параметр функции имеет тип, будь то нормальный тип, такой как int, float или универсальный тип. Если вы не предоставляете типы для параметра, это не означает, что он является параметром меньше, компилятор выведет тип на основе того, как используются параметры, и если в некоторых случаях он не сможет определить тип, он выдаст ошибку компилятора.

...