4

我已经看到了很多“真多态性”的部分定义,例如这里这里,但我无法通过两个具体示例找到一个明确的差异示例。

我知道重载+运算符是某种形式的多态性,并且它在 Haskell 和 C++ 中的实现方式不同。有人可以准确地说明两种语言的示例有什么区别吗?

4

2 回答 2

6

您正在寻找的术语是“参数多态性”,它不同于“临时多态性”。

参数多态的一个例子是在类型签名中Nothing

Nothing :: Maybe a

ain 类型可以是任何可以想象的类型,因为它存在于所有NothingsMaybe中。我们说它a是参数多态的,因为它可以是任何类型。

现在考虑这种类型:

Just 1 :: (Num b) => Maybe b

这次b不能是任何类型:它只能是 的实例类型Num。我们说它b是临时多态的,因为它可以是由Num类的实例给出的一组类型的任何成员。

所以,回顾一下:

  • 参数多态性:可以是任何类型

  • Ad-hoc 多态性:受类型类约束

于 2013-04-28T17:08:50.267 回答
3

您会经常遇到三种类型的多态性(使用 C++ 和 Haskell 示例)。

函数式语言中的参数多态性是类型系统的一个特征,其中函数的类型是对类型变量进行量化的表达式。输入类型约束签名中的自由参数,它决定了输出类型。例如,map 函数将一个函数作为其第一个参数,该参数确定输入列表和输出列表的类型。

map :: (a -> b) -> [a] -> [b]

用类型论的说法,签名通常写成:

 ∀ a. ∀ b. (a -> b) -> [a] -> [b]

C++ 可以通过模板实现参数多态的效果,但在我看来非常脆弱(即导致模糊的编译错误),缺乏找到的函数式语言中的形式主义:

template <class T>
T add(T a, T b) {
    return a+b;
}

Ad-hoc 多态性是指具有相同名称的函数在使用不同类型签名“查看”时行为不同。在 Haskell 中,这是用类型类表示的。a签名中的类型(+)绑定到实现Num类型类的类型。

(+) :: Num a => a -> a -> a

class Num a where
    (+) :: a -> a -> a

instance Num Int  where
    (+) = plusInt 

亚型多态性。Haskell 中不存在,但其他语言(Scala、ML)具有子类型多态性。在面向对象的语言中,这通常是一种语言特性,其中不同的对象实例实现同名的方法或属性调用,并根据对象模型的语义进行调度。以 C++ 为例:

class Animal {
public:
 virtual void speak() = 0;
};

class Cat : public Animal {
public:
 void speak() { 
    printf("Meow");
 }
};

class Dog : public Animal {
public:
 void speak() { 
    printf("Woof");
 }
};

关于多态性要记住的事情是将核心思想与实现分开。例如,ad-hoc 多态与类型类不同,它只是它的一种表达方式。

于 2013-04-28T19:45:54.963 回答