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