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

Я знаю, что, должно быть, мне здесь не хватает чего-то действительно очевидного. 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()

Есть идеи, зачем нужен актерский состав?

2 ответа

Решение

Часто, когда у вас есть рекурсивный набор методов, типы которых можно определить, 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# Команда будет весить.

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

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

Увидеть

Принудительный вывод типа F# для обобщений и интерфейсов, чтобы остаться свободным

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

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

Другие вопросы по тегам