Ограничение высших типов в Scala - PullRequest
7 голосов
/ 08 февраля 2012

Скажите, что у меня более высокий тип

SuperMap[Key[_],Value[_]]`.  

Предположим теперь, что у меня есть нечто более конкретное, требующее, чтобы параметр типа для Key совпадал с параметром для Value; то есть что-то вроде:

SuperDuperMap[T, Key[T], Value[T]]

Далее предположим, что я не хотел просто T, а очень специфический, где T <: OtherT

SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]]

Можно ли это сделать в Scala? Это просто плохая идея? Есть ли эквивалентный способ сделать это, который легче читать / писать / использовать?

Ответы [ 3 ]

11 голосов
/ 08 февраля 2012

Ваша декларация уже работает как положено, т.е. вы ограничиваете тип T, а также Key и Value.Однако, как вы написали, scala будет жаловаться, если вы выдадите что-то вроде

scala> class Foo[T <: OtherT, Key[T], Value[T]]
defined class Foo

scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
<console>:13: error: Key[SpecialOtherT] takes no type parameters, expected: one
              new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]

, поскольку типы Key и Value уже указаны в вашей предыдущей декларации.Следовательно, это будет работать

scala> new Foo[SpecialOtherT, Key, Value]
res20: Foo[SpecialOtherT,Key,Value] = Foo@3dc6a6fd

, что, вероятно, не так, как вы хотите.Вы можете сделать это следующим образом

scala> class Foo[T <: OtherT, K <: Key[T], V <: Value[T]]
defined class Foo

scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
res21: Foo[SpecialOtherT,Key[SpecialOtherT],Value[SpecialOtherT]] = Foo@7110506e

В нижней строке, поскольку типы Key и Value зависят исключительно от T, несколько избыточно иметь всю эту избыточную информацию при работе сFoo.Так почему бы не использовать внутреннее объявление типа следующим образом:

class Foo[T <: OtherT] {
  type K = Key[T]
  type V = Value[T]
}

Тогда у вас будет доступ к типам K и V из класса, но вам не нужно будет вводить его каждый раз при созданииновый ответ:

scala> new Foo[SpecialOtherT]
res23: Foo[SpecialOtherT] = Foo@17055e90

scala> new Foo[Int]
<console>:11: error: ...
3 голосов
/ 08 февраля 2012

Можно ли это сделать в Scala?

Что вы имеете в виду?Вы только что сделали!

Это просто плохая идея?

С чего бы это?На самом деле это отличная идея!Для этого предназначены типы с более высоким родом.

Есть ли эквивалентный способ сделать это, который легче читать / писать / использовать?

Чтение - читается очень хорошо для меня.

Запись - писать / тестировать / компилировать один раз, использовать везде.

Использование - Компилятор будетреконструировать (вывести) типы "везде".

2 голосов
/ 08 февраля 2012

Вам, вероятно, не нужно ничего более сложного, чем пара псевдонимов типов,

type SuperDuperMap[T, Key[_], Value[_]] = SuperMap[Key, Value]

type SuperDuperPooperMap[T <: OtherT, Key[_], Value[_]] = SuperMap[Key, Value]

Пример сеанса REPL,

scala> new SuperDuperMap[Int, Option, List] {}
res0: java.lang.Object with SuperDuperMap[Int,Option,List] = ...

scala> new SuperDuperPooperMap[OtherT, Option, List] {}
res1: java.lang.Object with SuperDuperPooperMap[OtherT,Option,List] = ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...