Scala:Java、C#、Scala 和 C++ 中的高级、开放类型和通配符泛型

Scala: Higher kinded, open-type and wild card generics in Java, C#, Scala and C++

本文关键字:Scala 类型 泛型 通配符 高级 Java C++      更新时间:2023-10-16

我一直在用C#编程,但对其类型系统的局限性感到沮丧。我了解到Scala的第一件事是Scala具有更高的泛型。但即使在我看过许多文章、博客条目和问题之后,我仍然不确定什么是高级泛型。无论如何,我写了一些编译良好的 Scala 代码,这个代码段使用更高的种类吗?

abstract class Descrip [T <: DTypes, GeomT[_ <: DTypes] <: GeomBase[_]](newGeom: NewGeom[GeomT])
{
  type GeomType = GeomT[T]
  val geomM: GeomT[T] = newGeom.apply[T]()  
}

然后我想也许我已经在使用更高种类的泛型了。据我所知,我是这样,但是当我现在理解它时,在我甚至听说过 Scala 之前,我已经很高兴地在 C# 中使用高级类型。这个狙击手使用更高种类的类型吗?

namespace ConsoleApplication3
{
    class Class1<T>
    {
        List<List<T>> listlist;
    }
}

因此,为了避免进一步的混淆,我认为澄清Java,C#和Scala中的每一个在高级类型,通配符和使用开放/部分开放类型方面允许的内容是有用的。由于C#和Scala之间的主要区别似乎是Scala允许通配符和开放类型,而C#没有通配符,并且要求在使用前关闭所有泛型类型。我知道它们有些不同,但我认为将这些功能的存在与C++模板中的等效功能联系起来会很有用。

那么以下正确吗?此表已针对阿列克谢的答案进行了更正

Lang:   Higher-kind Wild-card Open-types
Scala    yes         yes       yes
C#       no          no        no
Java     no          yes       no
C++      yes         yes       yes

这是高级类型不是:

不。高等类型是这样的

class Class1<T>
{
    T<String> foo; // won't compile in actual C#
}

即,其参数本身必须是泛型的泛型类型。请注意,在此示例中,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);
}

这些接口看起来很有用,因为它们为集合定义了一种"转换"(这称为"函子")。但它们看起来很像代码重复。但是你不能写一个"统一"的接口,无论是用Java还是C#。

它应该是什么样子的?你会很写这样的东西

interface Fun<X> {
   public <A,B> X<B> fmap(F<A,B> fn, X<A> col);
}
class ListFun implements Fun<List> {...}

但是X<A>在Java或C#中是不允许的,如果X不是像List这样的固定类型,而是一个类型参数。但是,如果以某种方式允许这种抽象(如在 Scala 或 Haskell 中),你就会有更高的种类类型(或"高阶类型多态性",术语仍然模糊不清)。以下是 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)
}

这是基本思想。通常你不会经常需要这些东西,但是当你需要它时,它可以非常有用。