[英]Scala partial application via underscore when composing function literals
我正在編寫函數文字,盡管與大多數示例不同,我看到的是我從一個多參數函數開始,然后進行了咖喱處理。
我有:
//types
case class Thing1(v: Double)
case class Thing2(v: Double)
case class Thing3(v: Double)
type Multiplier = Double
//functions
val f1 = (t: Thing1, m: Multiplier) => Thing2(m * t.v)
val f2 = (t: Thing2) => Thing3(t.v)
我想組成f1和f2以獲得組合功能
Thing1 => (Multiplier => Thing3)
如預期的那樣,以下內容無法編譯:
val fcomposed1 = f1.curried.andThen(f2) // does not compile
通過實驗,我能夠確定以下內容確實可以編譯並且具有正確的f簽名:
val fcomposed2 = f1.curried(_:Thing1).andThen(f2)
我讀過各種資料,例如Scala下划線的所有用途是什么? 可能相關的原因為什么Scala有時會自動應用thunk? 但不幸的是,我仍然無法確切地逐步了解這里發生的事情以及它為什么起作用。
此外,我希望將上面的分成兩個表達式與fcomposed2相同,但是第二個表達式不能編譯:
val f1partial = f1.curried(_:Thing1)
val fcomposed3 = f1partial.andThen(f2) // does not compile - same error as fcomposed1
看起來f1partial返回的簽名與f1.curried相同,這讓我進一步懷疑早期的fcomposed2是如何工作的。
有人可以一步一步解釋這兩種行為嗎?
在這里, _
充當lambda表達式的語法糖,但是在您可能沒有想到的水平上。
f1.curried
具有類型Thing1 => Multiplier => Thing2
f1.curried(_:Thing1)
與{ x: Thing1 => f1.curried(x) }
。 由於f1.curried(x)
的結果具有類型Multiplier => Thing2
,因此整個表達式的最終類型仍然是Thing1 => Multiplier => Thing2
。 因此,在結果( f1partial
andThen(f2)
上調用andThen(f2)
是無效的,因為函數f2( Thing2
)的輸入類型與前一個函數的輸出類型( Multiplier => Thing2
)不同。
相反, f1.curried(_:Thing1).andThen(f2)
擴展為{ x: Thing1 => f1.curried(x).andThen(f2) }
。 f1.curried(x)
計算結果為類型Multiplier => Thing2
,因此您可以在其上調用andThen(f2)
,從而得到一個Multiplier => Thing3
。 因此,整個表達式的計算結果為Thing1 => Multiplier => Thing3
如果您考慮以下兩個表達式之間的差異,可能會更清楚:
val fcomposed1 = { x: Thing1 => f1.curried(x).andThen(f2) } // valid
val fcomposed2 = { x: Thing1 => f1.curried(x) }.andThen(f2) // error
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.