Ric*_*ver 11 c# c++ java generics scala
我一直在用C#编程,但对其类型系统的局限性感到沮丧.我了解Scala的第一件事就是Scala具有更高的kinded泛型.但即使在我查看了一些文章,博客条目和问题之后,我仍然不确定什么是更高级的通用仿制药.无论如何我写了一些编译好的Scala代码,这段代码是否使用更高的类型?
abstract class Descrip [T <: DTypes, GeomT[_ <: DTypes] <: GeomBase[_]](newGeom: NewGeom[GeomT])
{
type GeomType = GeomT[T]
val geomM: GeomT[T] = newGeom.apply[T]()
}
Run Code Online (Sandbox Code Playgroud)
然后我想也许我已经在使用更高级的kinded泛型.正如我所理解的那样,但是现在我明白了,在我听说过Scala之前,我已经很高兴地在C#中使用了更高级的类型.这个snipet使用更高级的kinded类型吗?
namespace ConsoleApplication3
{
class Class1<T>
{
List<List<T>> listlist;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,为了避免进一步的混淆,我认为对于Java,C#和Scala中的每一个,在更高级的类型,外卡和开放/部分开放类型的使用方面,它们允许澄清是有用的.由于C#和Scala之间的关键区别似乎是Scala允许使用通配符和开放类型,因为C#没有通配符,并且要求在使用之前关闭所有通用类型.我知道它们有些不同,但我认为将这些特性的存在与它们在C++模板中的等价物联系起来会很有用.
以下是正确的吗?此表已针对Alexey的回答进行了更正
Lang: Higher-kind Wild-card Open-types
Scala yes yes yes
C# no no no
Java no yes no
C++ yes yes yes
Run Code Online (Sandbox Code Playgroud)
这是更高的kinded类型是不是:
不是.更高级的类型是类似的
class Class1<T>
{
T<String> foo; // won't compile in actual C#
}
Run Code Online (Sandbox Code Playgroud)
即通用类型,其参数必须是通用的.请注意,在此示例中Class1<IList>应该编译,但是Class1<String>或Class1<IDictionary>不应该编译.
您似乎需要了解更高级的类型,以及它们为何有用.
考虑以下接口(Java,F<X,Y>用作闭包替换):
interface ListFun {
public <A,B> List<B> fmap(F<A,B> fn, List<A> list);
}
interface SetFun {
public <A,B> Set<B> fmap(F<A,B> fn, Set<A> set);
}
Run Code Online (Sandbox Code Playgroud)
接口看起来很有用,因为它们为集合定义了一种"转换"(这称为"仿函数").但它们看起来非常像代码重复.但是你不能在Java和C#中编写"统一"的接口.
应该怎么样?你会很想写类似
interface Fun<X> {
public <A,B> X<B> fmap(F<A,B> fn, X<A> col);
}
class ListFun implements Fun<List> {...}
Run Code Online (Sandbox Code Playgroud)
但是X<A>在Java或C#中不允许,如果X不是类似固定类型List,而是类型参数.但是如果以某种方式允许这种抽象(比如在Scala或Haskell中),那么你有更高级别的kinded类型(或者"高阶类型多态",这个术语对此仍然是模糊的).这是Scala特征和实现:
trait Fun[X[_]] {
def fmap[A,B](fn: A => B, col:X[A]):X[B]
}
class ListFun extends Fun[List]{
def fmap[A,B](fn: A => B, list: List[A]) = list.map(fn)
}
Run Code Online (Sandbox Code Playgroud)
这是基本的想法.通常你不经常需要这些东西,但是当你需要它时,它可能是非常有用的.