为什么需要更高的种类?


13

一些语言允许带有类型参数的类和函数(例如,List<T>其中T可能是任意类型)。例如,您可以具有以下功能:

List<S> Function<S, T>(List<T> list)

但是,某些语言允许将此概念扩展到更高一级,从而使您可以使用带有签名的功能:

K<S> Function<K<_>, S, T>(K<T> arg)

其中K<_>本身是List<_>带有类型参数的类型。这种“部分类型”被称为类型构造函数。

我的问题是,为什么需要这种能力?之类的类型是有意义的,List<T>因为所有类型List<T>几乎都完全相同,但是所有类型K<_>可以完全不同。你可以有一个Option<_>List<_>具有完全没有常见的功能。


7
这里有几个很好的答案:stackoverflow.com/questions/21170493/...
itsbruce

3
@itsbruce特别是,Functor路易斯·卡西利亚斯(Luis Casillas)的答案中的例子非常直观。做什么List<T>Option<T>有什么共同点?如果您给我一个函数,T -> S我可以给您一个List<S>或函数Option<S>。他们的共同点是,您可以尝试T从两者中获取价值。
2015年

@Doval:你会怎么做?如果有人对后者感兴趣,那么我认为可以通过同时实现这两种类型来解决IReadableHolder<T>
超级猫

@supercat我猜他们将不得不执行IMappable<K<_>, T>与方法K<S> Map(Func<T, S> f),实施如IMappable<Option<_>, T>IMappable<List<_>, T>。因此,您将不得不限制K<T> : IMappable<K<_>, T>使用它。
GregRos

1
强制转换不是适当的类比。类型类(或类似构造)的作用是显示给定类型如何满足更高种类的类型。这通常涉及定义新功能或显示可以使用哪些现有功能(或方法,如果使用的是OO语言,如Scala)。完成此操作后,所有定义为与更高类型一起使用的功能都将与该类型一起使用。但这不只是接口,因为还定义了一组简单的功能/方法签名。我想我将不得不去写一个答案以显示其工作原理。
itsbruce

Answers:


5

由于没有人回答过这个问题,我想我自己去解决。我将不得不有点哲学。

泛型编程就是在不丢失类型信息的情况下对相似类型进行抽象(这是面向对象的值多态性所发生的)。为此,这些类型必须共享您可以使用的某种接口(一组操作,而不是OO术语)。

在面向对象的语言中,类型通过类来满足接口。每个类都有自己的接口,作为其类型的一部分定义。由于所有类List<T>共享相同的接口,因此无论T您选择哪种方式,都可以编写有效的代码。施加接口的另一种方法是继承约束,尽管两者看起来有所不同,但是如果考虑一下,它们有点相似。

在大多数面向对象的语言中,List<>它本身并不是适当的类型。它没有方法,因此没有接口。只有List<T>这些东西。从本质上讲,从技术角度来讲,唯一可以有意义抽象的类型是那种类型*。为了在面向对象的世界中使用种类繁多的类型,您必须以与该限制一致的方式来表达类型限制。

例如,如评论中所述,在某种意义上,如果您有一个函数,则可以将an转换为an ,或将a 转换为a ,因此我们可以将Option<>List<>视为“可映射的” 。记住不能使用类直接对更高类型的类型进行抽象,所以我们改用一个接口:Option<T>Option<S>List<T>List<S>

IMappable<K<_>, T> where K<T> : IMappable<K<_>, T>

然后我们实现该接口均List<T>Option<T>作为IMappable<List<_>, T>IMappable<Option<_>, T>分别。我们所做的是使用种类较多的类型对实际(非种类较高的)类型Option<T>和施加约束List<T>。这是在Scala中完成的方式,尽管Scala当然具有诸如traits,类型变量和隐式参数之类的功能,使其更具表现力。

在其他语言中,可以直接对更高类型的类型进行抽象。在Haskell(类型系统的最高权限之一)中,即使类型更高,我们也可以为任何类型使用类型类。例如,

class Mappable mp where
    map :: mp a -> mp b

这是一个直接约束在(带有mp一个类型参数的)(未指定)类型上的约束,并且要求它与map将an mp<a>转换为an 的函数相关联mp<b>。然后,我们可以编写函数来约束种类繁多的类型,Mappable就像在面向对象的语言中可以放置继承约束一样。好吧,有点。

综上所述,您使用高级类型的能力取决于您约束它们或将其用作类型约束的一部分的能力。


太忙于换工作了,但最终还是会抽出一些时间来写我自己的答案。不过,我确实认为您对约束的概念分心了。高级类型的一个重要方面是,它们允许定义函数/行为,这些函数/行为可以应用于逻辑上可以证明是合格的任何类型。类型类(对更高类型的一个应用程序)并没有对现有类型施加约束,而是为其添加了行为。
itsbruce 2015年

我认为这是语义问题。类型类定义类型的类。当您定义诸如之类的函数时(Mappable mp) => mp a -> mp b,已将约束置于mp类型类的成员上Mappable。当您声明某个类型(例如作为Option的实例)时Mappable,便会向该类型添加行为。我想您可以在不限制任何类型的情况下在本地使用该行为,但这与定义普通函数没有什么不同。
GregRos 2015年

另外,我很确定类型类与更高类型的类型没有直接关系。Scala具有类型较高的类型,但没有类型类,并且您可以将类型类限制为具有该类型的类型,而*不会使其不可用。但是,在使用更高种类的类型时,类型类确实非常强大。
GregRos 2015年

Scala具有类型类。它们用隐式实现。隐式提供等效的Haskell类型类实例。它比Haskell的实现更脆弱,因为它没有专用的语法。但这始终是Scala隐式函数的主要目的之一,它们可以完成工作。
itsbruce
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.