"True Polymorphism"的例子?(最好使用哈斯克尔)
Example of "True Polymorphism"? (Preferably, using Haskell)
我看过很多"真多态"的部分定义,例如这里和这里,但是我没有找到一个明确的例子来说明两个具体例子的区别。
我理解重载+
操作符是某种形式的多态性,它在Haskell和c++中实现不同。有人能用两种语言的例子准确地说明它们的区别吗?
您要查找的术语是"参数多态性",这与"ad-hoc多态性"不同。
参数多态性的一个例子是Nothing
的类型签名:
Nothing :: Maybe a
类型中的a
可以是任何可能的类型,因为Nothing
居住在所有Maybe
中。我们说a
是参数多态的,因为它可以是任何类型。
现在考虑这个类型:
Just 1 :: (Num b) => Maybe b
这次b
不能是任何类型:它只能是Num
的实例类型。我们说b
是ad-hoc多态的,因为它可以是由Num
类的实例给出的类型集合中的任何成员。
总结一下:
参数多态性:可以是任何类型
Ad-hoc多态性:受类型类约束
您将经常遇到三种类型的多态性(使用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多态性与类型类不同,它只是它的一个表达式。
- 莱克斯没有返回我想要的东西
- 斯塔克,堆栈,也可以在底部和顶部添加整数
- 皮克斯美元LNK2019:未解析的外部交易品种
- 东康斯泰克普/康斯蒂尼特/康斯特瓦尔在C++20 中允许吗?
- 康斯坦特还行,但不是康特克斯普尔?
- 快速计算变换/旋转马里克斯4x4
- 接口哈斯克尔和C++
- C++ 克鲁斯卡尔算法的实现
- 将unique_ptr传递给斯特托克
- 斯波伊素数猜想普里梅祖克
- 如何获得最后一个斯特托克
- 克鲁斯卡尔的算法解释
- 使用角落哈里斯知道角落的数字
- 克鲁斯卡尔算法用矢量转换
- 常量与变量上的常量与康特克斯PR
- 斯芬克斯在没有数据库的情况下工作吗
- C++ 如何实现双倍权重(而不是整数)的克鲁斯卡尔定理
- 如何计算哈斯克尔中的正弦函数
- "True Polymorphism"的例子?(最好使用哈斯克尔)
- 从C++到哈斯克尔类和状态