Использовать функциональный combinators на Кортежах Scala?

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

Мои попытки до сих пор:

scala> (3,4).map(_*2)    
error: value map is not a member of (Int, Int)
       (3,4).map(_*2)
             ^
scala> (3,4).productIterator.map(_*2)
error: value * is not a member of Any
       (3,4).productIterator.map(_*2)
                                  ^
scala> (3,4).productIterator.map(_.asInstanceOf[Int]*2)
res4: Iterator[Int] = non-empty iterator

scala> (3,4).productIterator.map(_.asInstanceOf[Int]*2).toList
res5: List[Int] = List(6, 8)

Это выглядит довольно болезненным... И я даже не начал пытаться преобразовать его назад в кортеж.
Я делаю его неправильно? Библиотека могла быть улучшена?

43
задан erip 7 June 2017 в 00:00
поделиться

1 ответ

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

scala> def map[A, B](as: (A, A))(f: A => B) = 
     as match { case (a1, a2) => (f(a1), f(a2)) } 
map: [A,B](as: (A, A))(f: (A) => B)(B, B)

scala> val p = (1, 2)    
p: (Int, Int) = (1,2)

scala> map(p){ _ * 2 }
res1: (Int, Int) = (2,4)

Вы можете использовать шаблон Pimp My Library для вызова этой функции как p.map(_ * 2).

UPDATE

Даже когда типы элементов не одинаковы, Tuple2[A, B] является бифунктором, который может быть отображен с помощью операции bimap.

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> val f = (_: Int) * 2
f: (Int) => Int = <function1>

scala> val g = (_: String) * 2
g: (String) => String = <function1>

scala> f <-: (1, "1") :-> g
res12: (Int, String) = (2,11)

UPDATE 2

http://gist.github.com/454818

35
ответ дан 26 November 2019 в 23:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: