2016-08-17 2 views
3

Давайте предположим, что у меня есть размораживание, который принимает несколько параметров типа:В Scala, возможно ли «curry» типа параметров def?

def foo[A, B, C](b: B, c: C)(implicit ev: Writer[A])

Однако предполагаемое использование является то, что параметры типа B и C должны быть выведены (основано на переданном в аргументе). И вызывающему абоненту должно быть нужно только явно указать A (например, чтобы иметь соответствующий имплицитный, выбранный компилятором). К сожалению, Scala позволяет только всем или любым параметрам типа указывать вызывающий. В некотором смысле, я хочу параметры типа для дубления:

def foo[A][B, C]...

Есть ли какой-то трюк, чтобы сделать это в Scala?

(Если мой конкретный пример не имеет полный смысл, я счастлив, чтобы улучшить его с предложениями.)

ответ

5

Лучшим способом я был в состоянии осуществить это является определением класса, который держит а затем использует метод apply для имитации вызова функции.

Я написал об этом здесь - http://caryrobbins.com/dev/scala-type-curry/

Для вашего конкретного примера, вы должны были бы поставить implicit ev: Writes[A] в подписи для apply и не в подписи для foo. Это связано с тем, что вызывает неоднозначность между явным передачей неявного аргумента или неявным вызовом метода apply.

Вот пример реализация для примера -

object Example { 
    def foo[A]: _Foo[A] = _foo.asInstanceOf[_Foo[A]] 

    final class _Foo[A] private[Example] { 
    def apply[B, C](b: B, c: C)(implicit ev: Writes[A]): Unit = ??? 
    } 

    private lazy val _foo = new _Foo[Nothing] 
} 

Вы можете поставить свой параметр типа вы хотите, чтобы снискать и следующие аргументы, передаваемые методу apply будут выведены.

Example.foo[Int]("bar", new Object) 

Если вы в конечном итоге нужно указать другие параметры типа, вы можете сделать это явным вызовом apply; хотя, я никогда не видел необходимости делать это еще.

Example.foo[Int].apply[String, Object]("bar", new Object) 

Если вы не хотите использовать промежуточный тип вы можете также использовать структурный тип, которые я обсуждаю в вышеупомянутой должности; однако для этого требуется reflectiveCalls и подпись предполагаемого типа, обоим из которых мне нравится избегать.

+1

Очень хорошо написано и очень умно! – Alec

Смежные вопросы