Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compose to methods, without duplicate input arguments

Tags:

scala

Suppose I have two methods

scala> def a(a: Int, b: Int, c: Int) : Int = …
a: (a: Int, b: Int, c: Int)Int

scala> def b(i: Int) : Int = …
b: (i: Int)Int

How to define a method c, that is the composition of both ? Unfortunately, the following code doen't compile :

def c = b(a)
like image 640
Yann Moisan Avatar asked Feb 05 '14 20:02

Yann Moisan


2 Answers

You could convert method a to function and then use method andThen like this:

def a(a: Int, b: Int, c: Int) : Int = a + b + c
def b(i: Int) : Int = i * 2

val c = (a _).tupled andThen b

c(1, 1, 1)
// 6

Note that I have to convert function (Int, Int, Int) => Int to tupled version - ((Int, Int, Int)) => Int - here to use andThen. So result function c accepts Tuple3 as argument.

You could convert c to untupled version ((Int, Int, Int) => Int) using Function.untupled:

val untupledC = Function.untupled(c)

untupledC(1, 1, 1)
// 6

shapeless

There is no untupled method for function arity > 5.

You could also use shapeless toProduct/fromProduct methods for any arity like this:

import shapeless.ops.function._
import shapeless.ops.function._

val c = (a _).toProduct.andThen(b).fromProduct
like image 63
senia Avatar answered Oct 03 '22 15:10

senia


Scalaz defines Functor instances for higher-arity functions, so you can just write

(a _).map(b)
like image 28
Hugh Avatar answered Oct 03 '22 14:10

Hugh