Я хотел бы передать объект функции, которая принимает аргумент с проецируемым типом, и получить Scala, чтобы вывести, что тип объекта поступает от объекта, который его охватывает. Вот несколько простых примеров, иллюстрирующих трудности:
trait Cult { cult_ =>
case class CultLeader(personality: Personality) {
val cult = cult_
val follower = personality.attractFollower(this)
}
case class Follower(leader: CultLeader, name: String)
}
trait Personality {
def attractFollower(leader: Cult#CultLeader) =
leader.cult.Follower(leader, "Fred") <-- THIS LINE FAILS TO COMPILE
}
Другими словами, личность CultLeaders должна привлекать последователя к тому же самому культу, что и CultLeader.
Компилятор Scala 2.11.2 говорит:
TypeProjection.scala:11: error: type mismatch;
found : Cult#CultLeader
required: leader.cult.CultLeader
leader.cult.Follower(leader, "Fred")
^
Он компилируется и запускается правильно, если я добавляю приведение, например:
leader.cult.Follower(leader.asInstanceOf[leader.cult.CultLeader], "Fred")
Это кажется неуклюжим, и он вводит проверку во время выполнения того, что должно быть выведено во время компиляции. По крайней мере, у меня есть обходной путь. Как я могу заставить компилятор Scala вывести, что тип leader
на самом деле leader.cult.CultLeader
?
Я бы предпочел не передавать cult
в качестве еще одного аргумента в attractFollower
. В моем действительном коде это может привести к уродливому прохождению параметра cult
- когда это действительно не нужно передавать вообще.