F #: Не удается скрыть сокращение типа в подписи? Почему бы и нет? - PullRequest
6 голосов
/ 18 мая 2010

В F # я хотел бы получить то, что я вижу в качестве стандартного абстрактного типа данных:

// in ADT.fsi
module ADT
  type my_Type

// in ADT.fs
module ADT
  type my_Type = int

Другими словами, код внутри модуля знает, что my_Type является int, а код снаружи - нет. Однако F #, похоже, имеет ограничение, когда аббревиатуры типов не могут быть скрыты подписью. Этот код выдает ошибку компилятора, и ограничение описано здесь .

Если my_Type был вместо этого дискриминационным объединением, то ошибки компилятора нет. У меня вопрос, почему ограничение? Кажется, я помню, что смог сделать это в SML и Ocaml, и, кроме того, разве это не довольно стандартная вещь при создании абстрактного типа данных?

Спасибо

Ответы [ 4 ]

10 голосов
/ 18 мая 2010

Как указывает Ганеш, это техническое ограничение компилятора F # (и среды выполнения .NET), потому что сокращение типа просто заменяется фактическим типом во время компиляции. В результате, если вы напишите функцию:

let foo (a:MyType) : MyType = a + 1

Компилятор скомпилирует его как метод .NET со следующей подписью:

int foo(int a);

Если фактический тип аббревиатуры был скрыт от пользователей библиотеки, то они не смогли бы распознать, что функция foo фактически работает с MyType (эта информация, вероятно, хранится в некотором F # специфические метаданные, но они недоступны для других языков .NET ...).

Возможно, лучший обходной путь для этого ограничения - определить тип как единичный дискриминируемый союз:

type MyType = MT of int
let foo (MT a) = MT(a + 1)

Работать с этим типом довольно удобно. Это добавляет некоторые накладные расходы (при создании значения типа создаются новые объекты), но это не должно быть большой проблемой в большинстве ситуаций.

5 голосов
/ 18 мая 2010

Сокращения типов в F # компилируются (т. Е. В скомпилированном коде будет использоваться int, а не MyType), поэтому вы не можете сделать их должным образом абстрактными. Теоретически, компилятор может принудительно применять абстракцию в мире F #, но это не очень полезно, так как все равно будет течь в других языках.

4 голосов
/ 18 мая 2010

Обратите внимание, что вы можете определить сокращение типа как частное в модуле:

// File1.fs
module File1
    type private MyType = int 
    let e : MyType = 42
    let f (x:MyType) = x+1

// Program.fs
module Program
do printfn "%A" (File1.f File1.e)

Мне непонятно, почему вы не можете скрыть это с подписью; Я зарегистрировал ошибку, чтобы рассмотреть это.

1 голос
/ 18 мая 2010

Насколько я понимаю, F # не позволяет скрывать аббревиатуру с помощью подписи.

Я нашел эту ссылку , где блогер прокомментировал это, но я не уверен в деталях, почему это так.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...