문제

I'm looking for a function that takes a tuple of functions over a common domain and returns a function from that domain to a tuple of their respective outputs. I'm assuming that such a utility is either built into Scala or is tucked away somewhere in Scalaz, but I have been unable to find it.

For example, the special case of a pair of functions (and taking the functions as individual arguments rather than a pair) would look like:

def pairFunc[I, O1, O2](f: I => O1, g: I => O2): I => (O1, O2) = (x: I) => (f(x), g(x))

Is there a way to achieve this for an arbitrary-arity tuple of functions?

EDIT:

A method on a Function type whose output looks like X -> ((A, B), C) and whose construction looks like f fZip g fZip h is just as fine as one a function whose output is X -> (A, B, C).

도움이 되었습니까?

해결책

You're in luck, scalaz (7) does have this with &&&:

  import scalaz._
  import Scalaz._

  val intToString = (i:Int) => i.toString
  val intPlusTwo = (i:Int) => i + 2

  val combined = intToString &&& intPlusTwo

  println(combined(1)) // (1, 3)

And you can continue to combine though it does build up tuples per what your comments would suggest:

  val combinedMore = intToString &&& intPlusTwo &&& intToString

  println(combinedMore(1)) // ((1,3),1)

다른 팁

You can define your own implicits and chain them using view bounds <%

// Add untupling capacity to a simple pair
implicit class EnrichTuple [A, B, C](f: (Function1[A, B], Function1[A, C])) {
  def untuple = (a: A) => (f._1(a), f._2(a))
}
// Add untupling capacity to a pair where the first member can implicitly be untupled
implicit class EnrichTuple2 [A, C, AB <% Function1[A, B] forSome { type B }](f: (AB, Function1[A, C])) {
  def untuple = (a: A) => (f._1(a), f._2(a))
}
// Add untupling capacity to a pair where the second member can implicitly be untupled
implicit class EnrichTuple3 [A, B, AC <% Function1[A, C] forSome { type C }](f: (Function1[A, B], AC)) {
  def untuple = (a: A) => (f._1(a), f._2(a))
}

val intToString = (i:Int) => i.toString
val intPlusTwo = (i:Int) => i + 2
val intTimesFour = (i: Int) => i * 4

val res1 = (intToString, intPlusTwo).untuple
val res2 = ((intToString, intPlusTwo), intTimesFour).untuple
val res3 = (intToString, (intPlusTwo, intTimesFour)).
res1(1)  // Returns (1, 3)
res2(1)  // Returns ((1, 3),4)
res3(1)  // Returns (1, (3, 4))
val res4 = ((intToString, intTimesFour), (intPlusTwo, intTimesFour )).untuple // Error 

The thing you also loose compared to the scalaz solution is the type of the result if there are nested tuples. And besides, you have the requirement that each time at least one of the two arguments of your pair is already a function.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top