2011-04-07 56 views
4

駕駛單類型這裏是一個很濃縮版:通過磚牆

case class Brickwall[A](otherSide: A) 
trait Monoman { def me(m: this.type): Unit } 

def test(m: Monoman): Unit = m.me(Brickwall(m).otherSide) 

-> error: type mismatch; 
found : Monoman 
required: m.type 

愚蠢的磚牆並不讓我通過。任何想法如何可能?祕密scala隧道效果?希望...

回答

6

據我所知,Scala編譯器拒絕推斷出路徑依賴的類型,所以有點類型註釋有助於:

def test(m: Monoman) { m.me(Brickwall[m.type](m).otherSide)} 
+0

謝謝moritz。嗯,是的,我應該說,我試圖解決強迫我的框架的用戶端正在寫這個,m.type ...這是一個DSL,我不想看到任何明確的打字如果可能的話。試圖找到一種解決方法來約束對獨特上下文的引用,以免它們逃脫。菲利普·哈勒和馬丁·奧德斯基發現了一篇非常有趣的論文(我以前見過但沒有注意):http://lamp.epfl.ch/~phaller/capabilities.html - 可能是我只需要解決這個想法,我想要的是不可能沒有編譯插件 – 2011-04-07 02:06:38

3

是的,單類型從由Scala編譯器推斷。

一種可能性是一個工廠方法添加到Monoman特點:

trait Monoman { 
    def me(m: this.type) : Unit 
    def createWall = Brickwall[this.type](this) 
} 

def test(m: Monoman) { m.me(m.createWall.otherSide) } 

也許這不是你的情況的可行解決方案。

+0

是的,我以前做過這個,但我實際上希望能夠得到任何類到我的系統,例如使用'new',因爲系統不應該被要求事先知道每個可能的類,它應該是可以從「外部」擴展的。我仍然可以使用一種類型作爲包裝,例如'Ref',然後做任何類型的隱式包裝和解包。我會試着看看我能否拿出一個例子來看看它是否透明。對不起,只有一個「接受」選項,你們兩個都值得。 – 2011-04-07 14:31:10

+0

一個可行的,但醜陋的解決方案是在Monoman中添加一個通用工廠:'def create [M [_]](implicit f:Monoman => M [Monoman])= f(this).asInstanceOf [M [this.type ]]' – 2011-04-07 15:40:44

1

這裏是工廠的想法試一下(我以前做過,放棄了,但也讓我們再試一次):

object Brickwall 
case class Brickwall[A](brick: A) 

trait Monoman { 
    var wall: Ref[this.type, Brickwall[String]] 
    def ref[V](v: V): Ref[this.type, V] 
} 

object Ref { 
    implicit def unwrap[Repr](r: Ref[_, Repr]): Repr = r.repr 
    implicit def wrap[A, Repr](repr: Repr): Ref[A, Repr] = new Impl[A, Repr](repr) 
    private class Impl[A, Repr](val repr: Repr) extends Ref[A, Repr] 
} 
trait Ref[A, Repr] { def repr: Repr } 

def test(m: Monoman): Unit = { 
    val w0 = m.wall 
    val w1 = w0.copy(brick = "3.1415") 
    m.wall = w1 // doesn't convert to Ref 
} 

因此而解纏是透明的,重新包裝不似乎正在工作,我懷疑它不可能得到它的工作,再次因爲m.type永遠不能推斷。