Компилятор F # требует ссылки на проект, но метод является приватным
Компилятор F # дает ошибку, говоря, что я должен добавить ссылку на проект, потому что тип, который я использую, имеет аргумент метода, который живет в этом проекте. Но этот метод является приватным!
У меня есть следующая структура проекта:
Программа → Библиотека → SubLibrary
SubLibrary содержит следующее:
namespace SubLibrary
type Widget = { Value: int }
Библиотека содержит следующее:
namespace Library
open SubLibrary
type Banana =
{ Value: int }
member private x.TakeWidget (w: Widget) = ()
Программа содержит следующее:
open Library
[<EntryPoint>]
let main argv =
printfn "%A" argv
let banana = { Value = 42 }
0
Я получаю эту ошибку:
error FS0074:
The type referenced through 'SubLibrary.Widget' is defined in an assembly that is not referenced.
You must add a reference to assembly 'SubLibrary'
Но метод TakeWidget
является закрытым!
Я попытался изменить Banana
на класс, а не на запись, но это не имело значения.
В качестве эксперимента я создал версию библиотеки С#, называемую библиотекой:
using SubLibrary;
namespace CLibrary {
public class CBanana {
int m_value;
public CBanana(int value) {
m_value = value;
}
private void TakeWidget(Widget w) {
}
}
}
Затем я изменил программу на использование CBanana
вместо Banana
:
open Library
[<EntryPoint>]
let main argv =
printfn "%A" argv
let banana = CBanana 42
0
Теперь я не получаю сообщение об ошибке. На самом деле, с С# я могу сделать этот метод общедоступным, и пока я не пытаюсь скомпилировать его, нет ошибки.
Почему компилятор настаивает на добавлении ссылки на SubLibrary? Конечно, я мог бы просто пойти и сделать то, что он мне сказал, для спокойной жизни, но SubLibrary - это частная деталь реализации библиотеки, которая не должна подвергаться программе.
Ответы
Ответ 1
Собственно, когда я пытался с классом вместо записи, он сделал трюк (F # 3.1):
type BananaClass (value:int) =
member private x.TakeWidget (w: Widget) = ()
member x.Value = value
Вы можете обойти его и с записью - вам нужно переместить частный член в отдельный модуль и получить его как расширение типа:
type Banana = { Value: int }
module Ext =
type Banana with
member x.TakeWidget (w: Widget) = ()
Компилятор не будет жаловаться на недостающую зависимость, пока не откроется модуль Ext
.
У меня нет хорошей идеи, почему компилятор жаловался в первую очередь. Вероятно, один из его причуд. Я не мог найти ничего серьезного подозрительного в сгенерированном ИЛ (кроме удивительного факта, что компилятор F # отмечает как частные, так и внутренние члены как внутренние в ИЛ - это не имело никакого значения здесь).
Ответ 2
Действительно, для меня это выглядит как ошибка, которую я поднял здесь, https://github.com/Microsoft/visualfsharp/issues/86. Таким образом, вы сможете отслеживать отзывы оттуда.