2014-02-06 57 views
-3

望着IO Monad的簽名部分來自Functional Programming in Scala理解類型參數

trait IO[+A] { self => 
    def run: A 
    def map[B](f: A => B): IO[B] = 
    new IO[B] { def run = f(self.run) } 

據我瞭解,IO[+A]IO類型需要的類型參數‘A或它的子類。’

看着def map[B]...B是涉及這個函數的類型。據我所知,使用map[B](f: A => B): IO[B]是有用的,因爲您可以列出B作爲返回類型f,以及返回的類型參數IO

所以,下面的實現會導致編譯時的問題:

map(f: Int => String): IO[Int]

+3

對不起,有什麼問題嗎? ;) –

+0

基本上我正在尋找確認/更多細節在我的上面的例子,請:) –

+0

我希望我回答你的問題。我認爲這是一個很好的問題,但它不容易措辭。 –

回答

1

所以+A意味着類似的事情,如T <: A。這意味着「對於A的所有亞型包括A」。這個「限制」在這裏很有用,因爲您應該將f函數傳遞給map方法,並且您將其限制爲特定類型A及其子類型。因此,當你在課堂上擴展特性時,允許在類型安全時替換f

B這裏是將f應用於A的結果。既然它是Monad,你不僅可以得到B,而且可以得到IO[B]。換句話說,它可能會失敗,你可能會得到B包裹在「成功」或某種「失敗」。

注意的self類型是+A,以及新創建IO[B]實際上並不計算任何東西,它只是圍繞一個run它必須是B的結果包裝。由於您預計在IO中發生故障,並且由於它是Monad,因此您可以圍繞創建單粒子f(self.run)的應用程序的結果(如map方法簽名所承諾的那樣)結果。

最後,如您所說map(f: Int => String): IO[Int]不應該編譯,因爲Int不是String的子類型。

3

我不確定在這種情況下「執行」的含義:map(f: Int => String): IO[Int]。如果您的意思是呼叫map傳遞一個函數Int => String,則返回IO[String] - 被調用者在返回的類型中沒有發言權。

如果你的意思是壓倒一切的mapoverride def map(f: Int => String): IO[String]執行(你不應該這樣做),那麼覆蓋任何東西,因爲覆蓋,當你無法刪除類型參數,你可以不更改它接收的參數的類型,並且可以將返回類型更改爲子類型,但IO[String]不是IO[B]的子類型,因此它也不同。