Ich würde gerne ein Objekt an eine Funktion übergeben, die ein Argument mit einem projizierten Typ akzeptiert, und Scala den Schluss ziehen, dass der Typ des Objekts von dem Objekt kommt, das es umgibt. Hier ist ein einfacher Code, die Schwierigkeit zu veranschaulichen:Warum kann Scala nicht den Pfad eines pfadabhängigen Typs ableiten - selbst von einer expliziten Selbstreferenz?
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
}
Mit anderen Worten, ein CultLeader Persönlichkeit einen Nachfolger zum gleichen Kult wie die CultLeader anziehen sollte.
Die Scala 2.11.2 Compiler sagt:
TypeProjection.scala:11: error: type mismatch;
found : Cult#CultLeader
required: leader.cult.CultLeader
leader.cult.Follower(leader, "Fred")
^
Es kompiliert und ordnungsgemäß ausgeführt wird, wenn ich eine Besetzung, wie folgt hinzufügen:
leader.cult.Follower(leader.asInstanceOf[leader.cult.CultLeader], "Fred")
Das ungeschickt scheint und es führt zur Laufzeit überprüft für etwas, das zur Kompilierzeit ableitbar sein sollte. Zumindest habe ich einen Workaround. Wie kann ich den Scala-Compiler dazu bringen, daraus abzuleiten, dass der Typ leader
tatsächlich leader.cult.CultLeader
ist?
Ich würde lieber cult
als ein weiteres Argument zu attractFollower
übergeben. In meinem tatsächlichen Code könnte das zu einer Menge hässlicher Umgehung des Parameters cult
führen - wenn es wirklich überhaupt nicht übergeben werden sollte.
Gibt es eine Möglichkeit zu verlangen, dass ein Follower vom gleichen Kult wie der "Anführer" des Anhängers ist? –
Ja, das war deine vorherige Lösung - aber du kannst keinen Anführer von ** irgendeinem ** Kult an einen Anhänger weitergeben, der einen Anführer von ** konkretem ** Kult erfordert - es gibt keine Möglichkeit, es während der Kompilierung zu überprüfen Scala weiß nicht, wie genau Ihr 'attractFollower' aufgerufen wird (es könnte ein Code außerhalb des Build-Moduls sein). Ihre Lösung besteht also darin, 'Any' zu übergeben, wenn die Funktion' Int' erfordert. Also keine Möglichkeit, eine konkrete Kultprojektion zu verlangen und gleichzeitig eine Projektion zu passieren - das ist logisch falsch. – dk14
Auch wenn 'attractFollower' von überall aufgerufen werden kann, sollte es nicht in der Lage sein, einen Follower des gleichen Kults wie den Leader zu erstellen, der an 'attractFollower' weitergegeben wurde? –