如何在scala中获得泛型(多态)lambda?

dk1*_*k14 11 polymorphism haskell scala type-inference

更新(2018年):我的祈祷在Dotty(Type Lambdas)得到了回答,因此以下问答更加"Scalac"相关


Scala只是一个简单的例子:

scala> def f(x: Int) = x
f: (x: Int)Int

scala> (f _)(5)
res0: Int = 5
Run Code Online (Sandbox Code Playgroud)

让我们通用:

scala> def f[T](x: T) = x
f: [T](x: T)T

scala> (f _)(5)
<console>:9: error: type mismatch;
 found   : Int(5)
 required: Nothing
              (f _)(5)
                    ^
Run Code Online (Sandbox Code Playgroud)

让我们看看Scala中的多态方法的eta扩展:

scala> f _ 
res2: Nothing => Nothing = <function1>
Run Code Online (Sandbox Code Playgroud)

与Haskell的比较:

Prelude> let f x = x

Prelude> f 5
5
Prelude> f "a"
"a"
Prelude> :t f
f :: t -> t
Run Code Online (Sandbox Code Playgroud)

Haskell在[T] => [T]这里确实推断出了正确的类型.

更现实的例子?

scala> identity _
res2: Nothing => Nothing = <function1>
Run Code Online (Sandbox Code Playgroud)

更现实:

scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T

scala> f _
res3: List[Nothing] => Nothing = <function1>
Run Code Online (Sandbox Code Playgroud)

你不能为身份制作别名 - 必须编写自己的功能.像[T,U](t: T, u: U) => t -> u(制作元组)这样的东西不可能用作价值观.更一般 - 如果你想传递一些依赖于泛型类型的lambda(例如:使用泛型函数,例如:创建列表,元组,以某种方式修改它们) - 你不能这样做.

那么,如何解决这个问题呢?任何解决方法,解决方案或推理?

PS我使用了术语多态lambda(而不是函数),因为函数只是名为lambda

lmm*_*lmm 7

只有方法在JVM/Scala上可以是通用的,而不是值.您可以创建一个实现某个接口的匿名实例(并为您要使用的每个类型都复制它):

trait ~>[A[_], B[_]] { //exists in scalaz
  def apply[T](a: A[T]): B[T]
}

val f = new (List ~> Id) {
  def apply[T](a: List[T]) = a.head
}
Run Code Online (Sandbox Code Playgroud)

或者使用无形' Poly,它支持更复杂的类型案例.但是,这是一个限制,它需要解决.

  • 它实际上与JVM没有多大关系,因为它发生在编译时(常规`Function`也可以看到解决方法).我同意,现在`Poly`似乎是最好的解决方案. (2认同)