Scala может позволить свободные Параметры Типа в аргументах (граждане первого класса Параметров Типа Scala?)?

Я слышал разговор о Jeff/Joel об этом на подкасте сегодня ( эпизод 34 , 2008-12-16 (MP3, 31  МБ), 1:03:38 secs - 1:06:45 secs), и я думал, что вспомнил Stack  Overflow использовал LINQ  to  SQL, но возможно это было угроблено. Вот то же самое в LINQ  to  SQL.

var inValues = new [] { "ruby","rails","scruffy","rubyonrails" };

var results = from tag in Tags
              where inValues.Contains(tag.Name)
              select tag;

Вот именно. И, да, LINQ уже смотрит назад достаточно, но Contains пункт кажется дополнительным назад мне. Когда я должен был сделать подобный запрос для проекта на работе, я естественно пытался сделать это неправильный путь путем выполнения соединения между локальным массивом и таблицей SQL Server, расчета LINQ  to  переводчик SQL был бы достаточно умен для обработки перевода так или иначе. Это не сделало, но это действительно предоставляло сообщение об ошибке, которое было описательным и указало на меня к использованию , Содержит .

Так или иначе, если Вы выполняете это в наиболее рекомендуемом LINQPad и выполняете этот запрос, можно просмотреть фактический SQL, который генерировал SQL поставщик LINQ. Это покажет Вам каждое из значений, параметризованных в IN пункт.

5
задан Qantas 94 Heavy 1 May 2014 в 09:08
поделиться

3 ответа

Вы можете сделать это так:

trait Forall {
  def f[Z] : Z=>Z
}

def z(u : Forall) = w(u.f[Int], u.f[Double])

Или используя структурные типы:

def z(u : {def f[Z] : Z=>Z}) = w(u.f[Int], u.f[Double])

Но это будет медленнее, чем первая версия, так как она использует отражение.

РЕДАКТИРОВАТЬ: Это как использовать вторую версию:

scala> object f1 {def f[Z] : Z=>Z = x => x}
defined module f1

scala> def z(u : {def f[Z] : Z=>Z}) = (u.f[Int](0), u.f[Double](0.0))
z: (AnyRef{def f[Z]: (Z) => Z})(Int, Double)

scala> z(f1)
res0: (Int, Double) = (0,0.0)

Для первой версии добавьте f1 extends Forall или просто

scala> z(new Forall{def f[Z] : Z=>Z = x => x})
6
ответ дан 18 December 2019 в 13:18
поделиться

If you're curious, what you're talking about here is called "rank-k polymorphism." See wikipedia. In your case, k = 2. Some translating:

When you write

f[X](x : X) : X = ... 

then you're saying that f has type "forall X.X -> X"

What you want for z is type "(forall Z.Z -> Z) -> Unit". That extra pair of parenthesis is a big difference. In terms of the wikipedia article it puts the forall qualifier before 2 arrows instead of just 1. The type variable can't be instantiated just once and carried through, it potentially has to be instantiated to many different types. (Here "instantiation" doesn't mean object construction, it means assigning a type to a type variable for type checking).

As alexy_r's answer shows this is encodable in Scala using objects rather than straight function types, essentially using classes/traits as the parens. Although he seems to have left you hanging a bit in terms of plugging it into your original code, so here it is:

// this is your code

object TypeExample {
  def main(args: Array[String]):Unit = {
    def f[X](x:X):X = x              // parameterize fn
    def v(f:Int=>Int):Unit = { }     // function that operates on an Int to Int function
    v(f)                             // applied, types correct
    v(f[Int])                        // appplied, types correct
    def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
    w(f[Int],f[Double])              // works

// This is new code

    trait ForAll {
      def g[X](x : X) : X
    }

    def z(forall : ForAll) = w(forall.g[Int], forall.g[Double])
    z(new ForAll{def g[X](x : X) = f(x)})
  }
}
6
ответ дан 18 December 2019 в 13:18
поделиться

Я не думаю, что то, что вы хотите делать, возможно.

Редактировать:

Моя предыдущая версия была ошибочной. Это действительно работает:

scala> def z(f: Int => Int, g: Double => Double) = w(f, g)
z: (f: (Int) => Int,g: (Double) => Double)Unit

scala> z(f, f)

Но, конечно, это в значительной степени то, что у вас есть.

Я не думаю, что это вообще возможно, потому что параметры типа существуют только во время компиляции. Во время выполнения такого нет. Так что для меня даже не имеет смысла передавать параметризованную функцию вместо функции с параметрами типа, определенными Scala.

И нет, в Scala нет макросистемы.

Во время выполнения такого нет. Так что для меня даже не имеет смысла передавать параметризованную функцию вместо функции с параметрами типа, определенными Scala.

И нет, в Scala нет макросистемы.

Во время выполнения такого нет. Поэтому для меня даже не имеет смысла передавать параметризованную функцию вместо функции с параметрами типа, определенными Scala.

И нет, в Scala нет макросистемы.

2
ответ дан 18 December 2019 в 13:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: