Scala泛型函数与泛型方法

Scala泛型函数与泛型方法,scala,types,existential-type,Scala,Types,Existential Type,到目前为止,我的印象是,在scala中定义泛型函数的唯一方法是使用方法,例如 def myToString[A](value: A) = {println(value)} 然而,我的想法如下: val myToStringFun: (T forSome {type T}) => Unit = value => println(value) 是否有我没有看到的东西,或者是在Scala中编写泛型函数而不使用方法的模式 我以前从未见过这种模式,只是根据我对更高级类型的学习和存在主义的概

到目前为止,我的印象是,在scala中定义泛型函数的唯一方法是使用方法,例如

def myToString[A](value: A) = {println(value)}
然而,我的想法如下:

val myToStringFun: (T forSome {type T}) => Unit = value => println(value)
是否有我没有看到的东西,或者是在Scala中编写泛型函数而不使用方法的模式

我以前从未见过这种模式,只是根据我对更高级类型的学习和存在主义的概念,提出了这种模式

请分享你的想法或智慧

编辑1:

如果上面所说的是正确的,为什么不使用这种模式,人们系统地求助于泛型函数的方法呢。这只是一个简单的符号吗

编辑2:

如果一个函数
(T表示某些{type T})=>单元
Any=>单元

然而,似乎

val mySeqToString: (Seq[T] forSome {type T}) => String = {
    case head +: tail => s"$head +: " + seqToString(tail)
    case Nil => "Nil"
}
val mySeqToString: (Seq[T] forSome {type T}) => String = {
  case head +: tail => s"$head +: " + seqToString(tail)
  case Nil => "Nil" 
}
相当于

def seqToString[T](seq: Seq[T]): String = seq match {
    case head +: tail => s"$head +: " + seqToString(tail)
    case Nil => "Nil"
}
def seqToString[T](seq: Seq[T]): String = seq match {
  case head +: tail => s"$head +: " + seqToString(tail)
  case Nil => "Nil" 
}

正确吗?

类型
函数中的A
是标准泛型类型。您可以使用它执行许多操作,例如要求一个typeclass实例:

import cats.implicits._
def myToString[A: cats.Show](value: A) = { println(value.show) }
另一方面,type
(T表示某些{type T})
是一种新的类型。您可能会通过它更流行的速记符号来识别它,
(例如
列表[\u]
)。你不能用那个。如果在中检查
值的类型

val myToStringFun: (T forSome { type T }) => Unit = value => println(value)
您会注意到它是
Any
。顺便说一句,对于某些is,通过
使用存在类型

函数在Scala中是单态的,不同于多态的方法。就我个人而言,我认为这篇文章对这个主题提供了很好的解释。

(T对于某些{type T})
只是
Any
,所以
(T对于某些{type T})=>Unit
Any=>Unit
,它是任意
a=>Unit
子类型

通常,一些{type T}
F[T]不是
F[Any]
(协变
F
就是这样,即
F[+X]
F[T]对于某些{type T}
aka
F[\u]
是所有类型的
F[a]
(包括
F[Any]
)的超类型。实际上,它是这样的最小超类型,即所有类型
F[A]
中的最小上界(对于固定
F
和任意
A

然而,似乎

val mySeqToString: (Seq[T] forSome {type T}) => String = {
    case head +: tail => s"$head +: " + seqToString(tail)
    case Nil => "Nil"
}
val mySeqToString: (Seq[T] forSome {type T}) => String = {
  case head +: tail => s"$head +: " + seqToString(tail)
  case Nil => "Nil" 
}
相当于

def seqToString[T](seq: Seq[T]): String = seq match {
    case head +: tail => s"$head +: " + seqToString(tail)
    case Nil => "Nil"
}
def seqToString[T](seq: Seq[T]): String = seq match {
  case head +: tail => s"$head +: " + seqToString(tail)
  case Nil => "Nil" 
}
对吗

没有

def seqToString[T](seq:seq[T]):字符串是通用的

val mySeqToString:(Seq[T]forSome{type T})=>String
是存在量化

seqToString: ((∃ T), (seq: Seq[T])) => String
在第一种情况下,您可以指定
T
,您的代码将用于此特定的
T
,例如
seqToString[Int]
将接受
Seq[Int]
seqToString[String]
将接受
Seq[String]

在第二种情况下,您不控制
T
,该方法接受所有
Seq[Int]
Seq[String]

因为
Seq
是协变的,所以对于某些{type T}
来说,
Seq[T]只是
Seq[Any]

在依赖类型的语言中,存在量化到Sigma类型,通用量化导致Pi类型。

Scala 3(Dotty)应该提供,因此类似于多态方法

scala> def myToString[A](value: A) = println(value)
def myToString[A](value: A): Unit
我们可以编写多态函数

scala> val myToString: [A] => A => Unit = [A] => (value: A) => println(value)
val myToString: PolyFunction{apply: [A](x$1: A): Unit} = <function1>
注意不要混淆多态函数类型

[A] => B
具有不同“级别”上的lambda类型

其中,箭头
=>>
中的第二个
指向类型级别


请注意,此功能仍在按照

进行开发,它不是一个存在的泛型,在这一点上,对于任何人来说,它只是一种奇特而混乱的语法。如果
T
在任何意义上都不可用,请尝试用它编写一个通用标识函数,或者编写一个函数,该函数接受
T
Ts
列表,并返回一个检查列表是否包含该元素的Boleean。有趣的是,编写
def方法[F[\u]](对于某些{type T},e:F[T]):String=??
就像说
e:F[Any]
???存在句与任何存在句都有点不同,特别是考虑到对象的变化,它们的行为不同。但是,我个人从未发现它们有用(而且,它们总是让我惊讶,所以公平地说,我真的不理解它们)。存在类型也将在Scala中删除。Scala 3将具有适当的,因此这将是一个通用函数,但是
val mySeqToString:(Seq[T]forSome{type T}=>String={case head+:tail=>s“$head+:”+seqToString(tail)case Nil=>“Nil”}
?编辑了我的问题,添加了反映您答案的第二个case。但总的来说,我将坚持使用方法来编写通用的内容,我想:)非常感谢您在这方面的扩展。在做了一些准备之后,我们必须回到这个问题上来:)@MaatDeamon是的,我正要评论你的第二个例子与第一个例子并没有太大的不同。我可以举一个例子,一开始它看起来像一个泛型:
val-genericFun:((T,List[T])对于一些{type T}=>Boolean={case(T,List)=>List.contains(T)}
,一个快速测试似乎表明它是有效的:
genericFun(3->List(1,3,5))
,我们可以看到,在这个测试的最后,它又一次出现了:
genericFun(3->List(1,0,”)
此外,主要的问题是我们不能在其他参数或返回类型中重用
T