Как специализировать параметризованный аргумент типа для нескольких различных типов в Scala? - PullRequest
8 голосов
/ 15 июня 2010

Мне нужна перепроверка (пожалуйста).

В статье (http://www.win -vector.com / blog / 2010/06 / автоматическая дифференциация со scala / ), которую я только что написал, я заявил, что это моя вера вScala, что вы не можете указать функцию, которая принимает аргумент, который сам является функцией с несвязанным параметром типа.Я отредактировал этот вопрос, чтобы попытаться упростить пример.

Следующий код работает путем введения черты GenericFn, которая имитирует черту Scala Function1, за исключением того, что в функции есть параметр свободного типа:

object TypeExample {
    trait NumberBase {
        def result:String
    }

    class A extends NumberBase {
        def result = "A"
    }

    class B extends NumberBase {
        def result = "B"
    }

    trait GenericFn {
        def apply[X<:NumberBase](x:X):String
    }

    def specializeAndApplyTwice(f:GenericFn):String = {
        f[A](new A()) + f[B](new B())
    }

    def main(args : Array[String]) : Unit = {
        val f = new GenericFn {
            def apply[X<:NumberBase](x:X):String = { x.result }
        }
        println(specializeAndApplyTwice(f))
    }
}

Это работает, но есть ли способ сделать это без черты GenericFn (использовать стандартную запись функции)?Например, приведенный ниже код завершается с ошибкой во время компиляции: «несоответствие типов; найдено: TypeExample2.A обязательно: _ $ 1, где тип _ $ 1 <: TypeExample2.NumberBase»: </p>

def specializeAndApplyTwice(f:(_<:NumberBase)=>String):String = {
   f(new A()) + f(new B())
}

1 Ответ

2 голосов
/ 26 июня 2010

Повторная начальная мотивация вопроса: мы хотим присвоить типу значение 'g', потому что мы хотим передать его. Значения Scala (конечно) не могут иметь полиморфный тип, даже если они являются функциональными значениями. Так как же дать тип, где какая-то его часть неизвестна?

Поэтому я считаю, что одним из решений является использование подстановочных знаков (форма экзистенциальной абстракции):


  def g(f: Array[_ &lt: NumberBase[_]] => Double, z: Array[Double]): Double

Прозаическое объяснение типа g: функция из Array [T] и Array [Double] в Double, где T - некоторый тип, расширяющий Double. «some» - это слово, которое указывает на экзистенциальную абстракцию, мы просим, ​​чтобы такой тип существовал, хотя на данном этапе нам все равно, какой это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...