2017-01-13 42 views
1

的,我有以下代碼Scala的類型推斷未能推斷類型的通用功能

def sendMoney[T <: MoneyType](fn: T => Future[T], input: T): Unit

被稱爲這樣

case x: Any => (sendMoney(_, _).tupled(x match { 
    case c: HoldsMoney => (createHold(_: HoldsMoney), c: HoldsMoney) 
    case r: ReserveMoney => (createReserve(_: ReserveMoney), r: ReserveMoney) 
}) 

HoldsMoneyReserveMoneyMoneyType基本類型。

Scala編譯器拋出以下錯誤。

missing parameter type for expanded function

注意,這個工作如果

x match { 
    case c: HoldsMoney => sendMoney(createHold(_: HoldsMoney), c) 
    case r: ReserveMoney => sendMoney(createReserve(_: ReserveMoney), r) 
} 

回答

3

考慮的

x match { 
    case c: HoldsMoney => (createHold(_: HoldsMoney), c: HoldsMoney) 
    case r: ReserveMoney => (createReserve(_: ReserveMoney), r: ReserveMoney) 
} 

類型的類型createHold(_: HoldsMoney)HoldsMoney => Future[HoldsMoney]createReserve(_: ReserveMoney)類型爲ReserveMoney => Future[ReserveMoney]

因爲函數在它們的參數類型中是相反的,所以這兩個函數的通用類型只能是Nothing => Future[MoneyType]。所以整個match的類型是(Nothing => Future[MoneyType], MoneyType),它不符合sendMoney的參數類型。

所以問題在於不可能爲sendMoney的參數的不同組合提供合適的通用類型。

+0

不錯。但爲什麼不是常見的類型爲'MoneyType => Future [MoneyType]'。他們有一個共同的基類後繼 –

+1

@FaizHalde那麼,'HoldsMoney <:MoneyType','未來[HoldsMoney] <:未來[MoneyType]'('未來'是協變的),但正如我所提到的'功能'是逆變在它的參數類型中,所以'HoldsMoney => Future [HoldsMoney]'不是'MoneyType => Future [MoneyType]'的子類型。這可能是違反直覺的,但當你考慮它時,它實際上是很自然的。也看到這個問題:http://stackoverflow.com/questions/10603982/why-is-function-a1-b-not-about-allowing-any-supertypes-as-parameters – Kolmar

+0

是的。混亂現在已經清除!謝謝。對我來說似乎是不可能的 –

0

我認爲你的目標是重構參數創建sendMoney並通過它們使用tupled。 我猜想你的代碼部分丟失了,爲了簡單起見刪除了類型邊界。

def sendMoney(fn: (MoneyType) => Future[MoneyType], input: MoneyType): Unit = println("sendMoney") 

def createHold(moneyType: MoneyType): Future[MoneyType] = ??? 
def createReserve(moneyType: MoneyType): Future[MoneyType] = ??? 

(sendMoney _).tupled(x match { 
    case c: HoldsMoney => (createHold, c) 
    case r: ReserveMoney => (createReserve, r) 
})