2013-10-12 4 views
3

Скажем, у меня есть несколько функций:transitive implicits - возможно ли это в Scala?

func1 : A => B 

func2: B => C 

func3: C => D 

Я хотел бы организовать в настоящее время функции, когда это необходимо в общем виде.

скажем, если мне нужно преобразование от A до B Я бы назвал func1. Но когда мне нужно преобразование от A до D Я хотел бы иметь состав этих функций. Возможно ли это в динамическом представлении?

+0

Учитывая implicits уже убить время компиляции и уменьшить общая читаемость вашего проекта и, следовательно, снижение общей производительности при работе над ним, то, что вы хотите, звучит как действительно плохая идея. – Esko

ответ

4

От Scala documentation for language features, объясняя, почему неявные преобразования должны быть явно включены в 2.10:

Почему это контролировать? Неявные преобразования, как известно, вызывают много ошибок , если они используются чрезмерно. И есть тенденция чрезмерно использовать их, потому что они выглядят очень мощными, и их эффекты кажутся легкими для понимания. Кроме того, в большинстве ситуаций использование неявных параметров приводит к лучшему дизайну , чем неявные преобразования.

Определенные пользователем неявные преобразования почти всегда являются плохими идеями, и сделать их переходными будет намного, намного хуже.

Вы можете, однако, использовать классы типов, чтобы получить аналогичный эффект более безопасным и контролируемым образом. Например, предположим, что мы имеем следующее:

trait MyConverter[A, B] { def apply(a: A): B } 

implicit def composeMyConverters[A, B, C](implicit 
    ab: MyConverter[A, B], 
    bc: MyConverter[B, C] 
) = new MyConverter[A, C] { def apply(a: A) = bc(ab(a)) } 

Теперь мы можем написать:

implicit object doubleToString extends MyConverter[Double, String] { 
    def apply(d: Double) = d.toString 
} 

implicit object intToDouble extends MyConverter[Int, Double] { 
    def apply(i: Int) = i.toDouble 
} 

def convertToString[A](a: A)(implicit as: MyConverter[A, String]) = as(a) 

И наконец:

scala> convertToString(13: Int) 
res0: String = 13.0 

Мы никогда четко определены конвертер из целых чисел в строки , но компилятор может использовать наш метод composeMyConverters для его создания, когда это необходимо.

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

+0

Мне нравится ваш подход Трэвиса, но, по сути, вы привязываетесь к ним, делая их транзитивными? –

+1

Да, но цепочка происходит автоматически, и они не являются неявными преобразованиями - это типы экземпляров класса, которые вызываются компилятором для удовлетворения неявных параметров. –

+1

не могли бы вы рассказать об этой разнице и почему это важно? –

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