2017-01-13 47 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) 
})