Неизвестная потребность в аннотации типа или литье

Я знаю, что я должен упустить что-то действительно очевидное здесь. 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()

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

Ответ 1

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

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

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

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

Ответ 2

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

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

См

Принудительно вызывать вывод типа F на дженериках и интерфейсах

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

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