2010-02-12 2 views
2

Я знаю, что, должно быть, мне не хватает чего-то действительно очевидного. B.GetInstance().Call() генерирует ошибку: Поиск объекта неопределенного типа на основе информации до этой точки программы. Аннотации типа могут потребоваться до этой точки программы, чтобы ограничить тип объекта. Это позволяет разрешить поиск.Неизвестная потребность в аннотации или отливке типа

Я использую v1.9.9.9.

type A() = 
    member x.Call() = B.GetInstance().Call() 

and B() = 
    static member GetInstance() = new B() 
    member x.Call() =() 

Я только что обнаружил, что это работает: (B.GetInstance() :> B).Call()

Любая идея, почему бросок необходимо?

ответ

7

Часто, когда у вас есть рекурсивный набор методов, типы которых выводятся, F # нуждается в помощи. Более приятная альтернатива была бы аннотировать определение B.GetInstance:

type A() = 
    member x.Call() = B.GetInstance().Call() 

and B() = 
    static member GetInstance() : B = new B() 
    member x.Call() =() 

Я считаю, что причина, вы столкнулись с этой проблемой является то, что F # пытается решить все выведенные типы на все методы A и B одновременно (потому что они определяются как взаимно-рекурсивные типы), и это приводит к проблемам, но, возможно, кто-то из команды F # будет взвешивать.

+0

Это неинтуитивно, чтобы понять это. Спас мой день, спасибо! – Cynede

7

Краткое резюме состоит в том, что в рекурсивной группе (например, члены одного типа или члены рекурсивных типов как мы здесь) F # читает объявления в порядке слева направо сверху вниз, а затем defi в порядке слева направо сверху вниз. Поэтому в этом случае, когда он достигает определения A.Call, он еще не прочитал определение из B.GetInstance и, следовательно, (до сих пор!) Не знает, что тип возврата GetInstance будет B.

Ответ Кита отвечает за эту ситуацию, вы можете указать аннотацию типа, чтобы указать тип возврата GetInstance в своем объявлении.

См

Forcing F# type inference on generics and interfaces to stay loose

для глубокого обсуждения того, что происходит здесь.

Заметим также, что в вашей первоначальной попытки, вам не нужно «бросить» (потенциально динамичную работу, используя :>), вместо этого вы можете просто «аннотировать» (статически объявить тип, используя :), чтобы получить его Скомпилировать. Но имеет смысл помещать аннотацию типа в объявление метода для GetInstance (как правило, предпочитают добавлять аннотации к сигнатурам методов вместо произвольных мест внутри тел).

+0

Отличное объяснение. Если бы я мог отметить два ответа, я бы это сделал. – Daniel

Смежные вопросы