Search code examples
scala

How to expand a function type to a function with more arguments


Given a function f: Function[A,B], is there a generic way to produce a function of type Function2[A, C, B] that ignores the second argument? And more generically, expand any function type to take any number of arguments that are ignored?


Solution

  • I am not entirely sure why you want something like this but for number of arguments fixed to 2, you can do something basic like

    def expandF[A, B, C](f: A =>B) : Function2[A, C, B] = 
      (a: A, c: C) => f(a)
    

    In this case the following call to a will still return 10

    def f1(a: Int) = {
      a + 5
    }
    
    val a = expandF(f1)
    
    a(5, "Hello")
    

    The generic version is more difficult for a few reason

    1. The number of function arguments in Scala 2 is upper bounded by 22 so it will never be truly generic (this limit was dropped in Scala 3 )

    2. Scala's static strict type system will start to get annoyed by this in the truest generic scenario. You can use _* which allows you to pass a collection of arguments but given the collections are homogenous, you will be limited to a single type across the arguments.

    This is where generic programming using Shapeless would come into play. You can abstract over the arity using shapeless, see the linked question.

    How can I use Shapeless to create a function abstracting over arity

    And then define an expand function like above that constructs one of these variable arity functions from a unary function.

    Without knowing exactly what purpose this serves and the use cases, it is very hard to come up with a one size fits all approach. Depending on how you want this transformation applied, you might even need to write a macro. This is all I can provide with the information at hand