如何解决Scala泛型函数与泛型方法
到目前为止,我的印象是,在scala中定义泛型函数的唯一方法是使用方法
def myToString[A](value: A) = {println(value)}
但是我想出了以下方法:
val myToStringFun: (T forSome {type T}) => Unit = value => println(value)
是否有我看不见的东西,还是在不使用方法的情况下在Scala中编写泛型函数的模式?
我以前从未见过这种模式,只是根据我对“高级类型”和“存在性...”概念的了解而提出的。
请分享您对此的想法或智慧。...
EDIT1:
如果上述正确,为什么不使用此模式而人们系统地使用通用函数方法。这只是一种简便的表达方式
EDIT2:
如果函数为(T forSome {type T}) => Unit
Any => Unit
但是,似乎
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"
}
正确吗?
解决方法
函数中的类型A
是标准的泛型类型。您可以使用它做很多事情,例如要求一个typeclass实例:
import cats.implicits._
def myToString[A: cats.Show](value: A) = { println(value.show) }
另一方面,键入(T forSome {type T})
是existential type。您可能会以其更流行的速记符号_
(例如List[_]
)来识别它。您不能对此做太多。如果您在{p>中检查value
的类型
val myToStringFun: (T forSome { type T }) => Unit = value => println(value)
您会注意到它是Any
。顺便说一句,通过forSome
使用存在类型为being dropped。
在Scala中,函数是单态的,与多态的方法不同。我个人认为,this文章对此主题做了很好的解释。
, (T forSome { type T })
只是Any
,所以(T forSome { type T }) => Unit
是Any => Unit
,它是任意A => Unit
的子类型。>
通常F[T] forSome { type T }
不是F[Any]
(对于协变F
就是F[+X]
来说是如此)。 F[T] forSome {type T}
亦称F[_]
是所有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" }
等同于
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
是通用的quantification
seqToString: (∀ T) => (seq: Seq[T]) => String
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
是协变的,所以Seq[T] forSome { type T }
只是Seq[Any]
。
在依赖类型语言对Sigma类型的存在量化leads中,通用量化导致Pi类型。
,Scala 3(Dotty)应提供polymorphic function types,类似于多态方法
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>
等效于PolyFunction
,它使用多态apply
方法进行了精炼
scala> val myToString: PolyFunction {def apply[A](value: A): Unit} = new PolyFunction {
| def apply[A](value: A): Unit = println(value)
| }
val myToString: PolyFunction{apply: [A](value: A): Unit} = <function1>
请不要混淆多态函数类型
[A] => B
lambda类型位于另一个“级别”上
[A] =>> B
其中箭头>
lifts中第二个=>>
为类型级别。
请注意,此功能仍按照documentation is missing polymorphic functions #7594进行操作
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。