2014-11-10 5 views
4

Можно использовать один одномерный массив как функцию вДвумерный массив как функцию

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

Можно использовать функцию с двумя списками аргументов в

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

Могу ли я объявить функция, которая будет принимать двумерный массив Array(Array(1)) без фактического использования типа объявления Array? Или он неявно преобразован в Int => Array[Int] и все?

+0

Дело 'foo1' работает, потому что' Array' неявно преобразуется в 'WrappedArray', который расширяет' Function [Int, _] '. Другой не по нескольким причинам: преобразование не будет применяться к внутренним массивам, а 'WrappedArray' не ковариантно, поэтому даже если преобразование действительно применимо,' WrappedArray [WrappedArray [Int]] 'doesn ' t расширять 'WrappedArray [Int => Int]'. –

ответ

2

Для произвольных вложенных массивов можно использовать "глубокий" неявное преобразование с гимнастикой типа

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) 
    } 

Пример в консоли scala

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> 

Это работает:

def foo(f: Int => Int => Int => Int) = println(f(0)(0)(0)) 
    foo(Array(Array(Array(1))).asFunction) 
0

Вы можете использовать это неявное преобразование

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) 

или без неявного преобразования

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

Спасибо. Хотя мне интересно, можно ли сделать такое преобразование для массива произвольного размера с какой-то странной типом гимнастики? – synapse

-1

Ну, а почему бы не что-то вроде этого?

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) 
    } 

} 

Или я просто полностью упустил вопрос?

+0

Он «работает», но он не является типичным - ваши 'fooNforFunctions' будут принимать любые' f: Int => X' и терпят неудачу во время выполнения, если 'X' является, например. 'String'. Пользователи Scala обычно ожидают хорошо типизированный код. – lmm

Смежные вопросы