Неизвестная потребность в аннотации типа или приведении - PullRequest
2 голосов
/ 13 февраля 2010

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

7 голосов
/ 13 февраля 2010

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

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

См

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

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

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

7 голосов
/ 13 февраля 2010

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

...