我有幾個具有相同簽名的通用函式:
def f1[A, B](v: A, f: (A, B) => B): B = ...
def f2[A, B](v: A, f: (A, B) => B): B = ...
我需要定義一個g可以接受任何這些函式 ( f1 f2) 的函式:
def g(f: ????) = ...
g 內部使用多個引數型別,所以我不能像這樣引數化它:
def g[A, B](f: (A, (A, B) => B) => B) = ...
uj5u.com熱心網友回復:
在 Scala 2 中確實沒有更好的方法來做到這一點。雖然你的解決方案有點奇怪,因為FunctionHolder的apply方法將回傳一個函式物件并且本身不接受任何引數——這比它需要的要復雜一些是。所以你可以這樣做:
trait FunctionHolder {
def apply[A, B](v: A, f: (A, B) => B): B
}
def g(f: FunctionHolder) = …
但這并沒有那么好。
在 Scala 3 中,有多態函式型別可以以更簡潔的方式執行此操作:
def g(f: [A, B] => (A, (A, B) => B) => B) = …
也就是說,我不相信那種型別簽名真的是你想要的。請記住,當您定義帶有型別引數的函式時,它需要適用于用戶可能提供的所有可能的型別引數。對于此簽名無法做到這一點......
def f1[A, B](v: A, f: (A, B) => B): B
...因為當我有一個這樣的函式時,我可以輕松地撰寫一個型別的運算式Nothing:
f1[Unit, Nothing]((), (a: Unit, b: Nothing) => b)
Nothing除非你作弊(例如拋出例外或進入無限回圈或類似的東西),否則不可能撰寫型別運算式。所以型別簽名告訴我你在作弊 ??
如果您想了解更多關于這種推理的資訊,請搜索“免費定理!”
uj5u.com熱心網友回復:
徘徊了一會兒后,想出以下內容:
g(new FunctionHolder {
def apply[A, B](): (A, (A, B) => B) => B = f1
})
def g(f: FunctionHolder) = f()(..., (a, b) => ...)
abstract class FunctionHolder {
def apply[A, B](): (A, (A, B) => B) => B
}
但這看起來不對。
希望有更簡潔的方法來做到這一點
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/393180.html
