簡體   English   中英

編寫函數文字時通過下划線實現Scala部分應用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM