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

HoldsMoney и ReserveMoney имеют базовый тип MoneyType.

Компилятор 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

Nice. Но почему не общий тип как «MoneyType => Future [MoneyType]». У них есть общий базовый класс afterall –

+1

@FaizHalde Ну, 'HoldsMoney <: MoneyType',' Future [HoldsMoney] <: Future [MoneyType] '(' Future' является ковариантным), но, как я уже говорил, 'Function' является контравариантным в своем типе аргументов, и поэтому '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) 
})