Pregunta

'mapa' conserva el número de elementos, por lo que usarlo en una tupla parece sensato.

Mis intentos hasta ahora:

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)

Parece bastante doloroso ... Y yo ni siquiera han comenzado a tratar de volver a convertirlo en una tupla.
¿Lo estoy haciendo mal? Podría mejorarse la biblioteca?

¿Fue útil?

Solución

sin forma admite la asignación y plegado de tuplas a través de una representación HList intermediario,

sesión de REPL de muestras,

scala> import shapeless._ ; import Tuples._
import shapeless._
import Tuples._

scala> object double extends (Int -> Int) (_*2)
defined module double

scala> (3, 4).hlisted.map(double).tupled
res0: (Int, Int) = (6,8)

Cuando los elementos de la tupla son de diferentes tipos que puede asignar una función polimórfica con el tipo casos específicos,

scala> object frob extends Poly1 {
     |   implicit def caseInt     = at[Int](_*2)
     |   implicit def caseString  = at[String]("!"+_+"!")
     |   implicit def caseBoolean = at[Boolean](!_)
     | }
defined module frob

scala> (23, "foo", false, "bar", 13).hlisted.map(frob).tupled
res1: (Int, String, Boolean, String, Int) = (46,!foo!,true,!bar!,26)

Actualizar

A partir del informe 2.0.0-M1 mapeo sobre tuplas se apoya directamente. Los ejemplos anteriores ahora se ven así,

scala> import shapeless._, poly._, syntax.std.tuple._
import shapeless._
import poly._
import syntax.std.tuple._

scala> object double extends (Int -> Int) (_*2)
defined module double

scala> (3, 4) map double
res0: (Int, Int) = (6,8)

scala> object frob extends Poly1 {
     |   implicit def caseInt     = at[Int](_*2)
     |   implicit def caseString  = at[String]("!"+_+"!")
     |   implicit def caseBoolean = at[Boolean](!_)
     | }
defined module frob

scala> (23, "foo", false, "bar", 13) map frob
res1: (Int, String, Boolean, String, Int) = (46,!foo!,true,!bar!,26)

Otros consejos

En general, los tipos de elementos de una tupla no son los mismos, por lo que el mapa no tiene sentido. Se puede definir una función para manejar el caso especial, sin embargo:

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)

Se puede usar el patrón Pimp My Library para llamar a esto como p.map(_ * 2).

Actualizar

Aun cuando los tipos de los elementos no son los mismos, Tuple2[A, B] es un bifuntor , que puede ser mapeado con la operación 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)

ACTUALIZACIÓN 2

http://gist.github.com/454818

función de mapa obtiene una A => B y vuelve F[B].

def map[A, B](f: A => B) : F[B]

Como retronym escribió Tuple2 [A, B] es un bifuntor, por lo que puede buscar la función BIMAP en scalaz o gatos.
BIMAP es una función que asigna a ambos lados de la tupla:

def bimap[A, B, C, D](fa: A => C, fb: B => D): Tuple2[C, D]

Debido Tupla [A, B] tiene 2 valores y sólo un valor se puede asignar (por convención, el valor de la derecha), sólo puede devolver el mismo valor para el lado izquierdo y el derecho de usar función para asignar el valor correcto de la tupla.

(3, 4).bimap(identity, _ * 2)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top