4

It's possible to use a one-dimensional array as a function in

def foo1(f: Int => Int) = ???
foo1(Array(1))

It's possible to use a function with two argument lists in

def foo2(f: Int => Int => Int) = ???
def plus(x: Int)(y: Int) = x + y
foo2(plus)

Can I declare a function that will accept a two-dimensional array Array(Array(1)) without actually using Array type in function declaration? Or is it implicitly converted to Int => Array[Int] and that's it?

1
  • The foo1 case works because the Array gets implicitly converted into a WrappedArray, which extends Function[Int, _]. The other doesn't for a couple of reasons: the conversion won't apply to the inner arrays, and WrappedArray isn't covariant, so even if the conversion did apply, WrappedArray[WrappedArray[Int]] doesn't extend WrappedArray[Int => Int]. Commented Nov 10, 2014 at 17:57

3 Answers 3

2

For arbitrary nested arrays you can use "deep" implicit conversion with type gymnastics

  trait ToIdxFunction[X[_], A] {
    type Result
    def toIdx(x: X[A]): Int => Result
  }

  trait LowerPriorityDeepFunctor {
    implicit def plainArray[A] =
      new ToIdxFunction[Array, A] {
        type Result = A
        def toIdx(x: Array[A]): Int => Result = {
          i => x(i)
        }
      }
  }

  object ToIdxFunction extends LowerPriorityDeepFunctor {
    implicit def nestedArray[A](implicit inner: ToIdxFunction[Array, A]) = {
      new ToIdxFunction[Array, Array[A]] {
        type Result = Int => inner.Result
        def toIdx(x: Array[Array[A]]): Int => Result = {
          i => inner.toIdx(x(i))
        }
      }
    }
  }

  import ToIdxFunction._

  implicit class Ops[X[_], A](self: X[A]) {
    def asFunction(implicit F: ToIdxFunction[X, A]) = F.toIdx(self)
  }

Example in scala console

scala> Array(1).asFunction
res4: Int => Int = <function1>

scala>   Array(Array(1)).asFunction
res5: Int => (Int => Int) = <function1>

scala>

scala>   Array(Array(Array(1))).asFunction
res6: Int => (Int => (Int => Int)) = <function1>

scala>   Array(Array(Array(Array(1)))).asFunction
res7: Int => (Int => (Int => (Int => Int))) = <function1>

This works:

  def foo(f: Int => Int => Int => Int) = println(f(0)(0)(0))
  foo(Array(Array(Array(1))).asFunction)
Sign up to request clarification or add additional context in comments.

Comments

0

You can use this implicit conversion

  def foo2(f: Int => Int => Int) = println(f(0)(0))

  implicit def arrTof[T](arr: Array[Array[Int]]): Int => Int => Int =
    arr.apply _ andThen (_.apply)

  val arr2 = Array(Array(10))
  foo2(arr2)

or without implicit conversion

  foo2(arr2.apply _ andThen (_.apply))

1 Comment

Thanks. Though I wonder is it possible to make such a conversion for an array of arbitrary dimension with some weird type gymnastics?
-1

Well, and why not something like this?

object Main {

  def fooNforFunctions(f: Int => _): Unit = {
    f(0) match {
      case g: Array[_] =>
        fooNforFunctions(g)
      case i: Int =>
        println(i)
    }
  }

  def main(args: Array[String]): Unit = {
    val arr3 = Array(Array(Array(3)))
    val arr4 = Array(Array(Array(Array(4))))

    fooNforFunctions(arr3)
    fooNforFunctions(arr4)
  }

}

Or I just completely missed the point of the question?

1 Comment

It "works", but it's not typesafe - your fooNforFunctions will accept any f: Int => X and fail at runtime if X is e.g. String. Scala users generally expect well-typed code.

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.