0

I am wondering whether the following is possible in Scala:

Given some vector x = (x_1, x_2, ..., x_n) in R^n and a function f that maps R^n to R, I would like to replicate this concept in Scala. The idea of Scala's partial function/currying should hold here (i.e. when applying a single value x_i, return a function that is defined only for a subset of its input domain). For example, when n = 2 define f(x, y) = sin(x + y), then trivially, f(2, y) = sin(2 + y).

However, the dimension (n > 0) may vary from case to case and may even be provided in input.

Partial application for n = 2 is:

def leftPartialFunction(f: (Double, Double) => Double)(x: Double): Double => Double = f(x, _)

but how can this be generalized for arbitrary n? For example, how can I apply the function in position i? Something like this I assume would not work:

def partialFunction(f: IndexedSeq[Double] => Double)(xi: Double): IndexedSeq[Double] => Double =  .... // cannot work well with indexed seq as they are not "disjoint"
7
  • leftPartialFunction looks like currying ((Double, Double) => Double) => Double => Double => Double Commented Jan 23, 2023 at 22:11
  • @DmytroMitin indeed it is Commented Jan 23, 2023 at 22:12
  • Are you trying to define ((A1, ..., An) => B) => A1 => ... => An => B for arbitrary n? Commented Jan 23, 2023 at 22:13
  • 1
    "Abstracting over arity" github.com/milessabin/shapeless/wiki/… Commented Jan 23, 2023 at 22:17
  • What do you mean by "indexed seq are not "disjoint""? Commented Jan 23, 2023 at 22:21

1 Answer 1

1

Try the following implementation of partialFunction:

import shapeless.{::, HList, HNil, Nat, Succ}
import shapeless.ops.function.{FnFromProduct, FnToProduct}
import shapeless.ops.hlist.{At, Drop, Prepend, Take}

def partialFunction[N <: Nat, F, X,
                    L <: HList, Y, L1 <: HList, L2 <: HList, L3 <: HList
                   ](i: N)(f: F)(xi: X)(implicit
  fnToProduct: FnToProduct.Aux[F, L => Y],
  at: At.Aux[L, N, X],
  take: Take.Aux[L, N, L1],
  drop: Drop.Aux[L, Succ[N], L2],
  prepend: Prepend.Aux[L1, L2, L3],
  fnFromProduct: FnFromProduct[L3 => Y],
  take1: Take.Aux[L3, N, L1],
  drop1: Drop.Aux[L3, N, L2],
  prepend1: Prepend.Aux[L1, X :: L2, L],
): fnFromProduct.Out =
  fnFromProduct(l3 => fnToProduct(f)(prepend1(take1(l3), xi :: drop1(l3))))

Testing:

import shapeless.Nat._1

val f: (Int, Boolean, Double) => String = (i, b, d) => s"i=$i, b=$b, d=$d"

f(1, true, 2.0) // i=1, b=true, d=2.0

val f1 = partialFunction(_1)(f)(true)

f1: ((Int, Double) => String)

f1(1, 2.0) // i=1, b=true, d=2.0

You can also write partialFunction(Nat(1))(f)(true) instead of partialFunction(_1)(f)(true).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.