gpt4 book ai didi

list - 为什么 Haskell 允许 Shape 列表,但不允许 Square 或 Circle 或 Triangle 列表

转载 作者:行者123 更新时间:2023-12-01 14:03:09 25 4
gpt4 key购买 nike

为什么 Haskell 允许像第一个例子那样做一个 Shape 列表,而不像第二个例子那样?据我所知,这两个列表的元素都是

{ name :: String, position :: Vector3D, radius :: Double }

{ name::String, position::Vector3D, dimensions::Vector3D }.

例 1:

data Shape
= Sphere { name :: String, position :: Vector3D, radius :: Double }
| Prism { name :: String, position :: Vector3D, dimensions :: Vector3D }

例 2:

data Sphere = Sphere { name :: String, position :: Vector3D, radius :: Double }
data Prism = Prism { name :: String, position :: Vector3D, dimensions :: Vector3D }

我想知道为什么可以创建 Shape 列表,但不能创建 Sphere 和 Prism 的多态列表,即使它们具有与通过数据类型“Shape”声明时相同的成员。

最佳答案

不同类型

在你的第二个例子中,

data Sphere = SphereTag { sphereName :: String, 
spherePosition :: Vector3D,
sphereRadius :: Double }
data Prism = PrismTag { prismName :: String,
prismPosition :: Vector3D,
prismDimensions :: Vector3D }

您已声明这是两种不同的数据类型。您可以使用类型 [Sphere][Prism] 但不能使用 [Shape] (因为您还没有定义 Shape 在这个例子中输入)。

我重命名了这些字段,因为否则 name 有两种类型 name::Sphere -> Stringname::Prism -> String,如果不使用类型类,这是不允许的。

我重命名了 SphereTagPrismTag 以清楚区分类型 Sphere 和数据构造函数 SphereTag

一种类型

在第一个例子中

data Shape
= SphereShape { name :: String, position :: Vector3D, radius :: Double }
| PrismShape { name :: String, position :: Vector3D, dimensions :: Vector3D }

一个类型,因此您可以制作[Shape]

任一个 - 标记联合

结合两种类型的经典方法是使用 Either,它用 LeftRight 标记来自两种类型的数据:

type PrismOrSphere = Either Prism Sphere

myList = [Left (SphereTag "this" ...), Right (PrismTag "that" ....), ....]

但您可能最好使用自定义 Shape 类型。

来自 OOP 的建议

尽量不要将 OOP 教学示例重新用作函数式编程示例。 OOP 示例旨在首先教您 OO 原则,其次教您编程,它们非常适合开发您的 OO 和命令式思维。

这就像试图通过在空旷的 parking 场周围操纵飞机来学习驾驶飞机。在飞机上绕着 parking 场慢慢走是非常困难的,而这可能是您开车时学到的第一件事。

如果您坚持通过尝试复制您的驾驶类(class)来学习飞行,您只会将您的飞机视为一种非常不方便的汽车,不适合在很多道路上行驶。

您应该使用一组编写良好的示例来教授函数式编程。我推荐Learn You a Haskell for Great Good它有网络版和死树版。

OOP 与 FP 中的多态

在面向对象编程中,通常所说的多态性是使用父类(super class)实现的。您可以拥有由 Shape 的子类型组成的 ShapeList 或由经理和清洁工组成的 EmployeeList,但是在传统的 OOP 中,您需要编写不同但相似的代码来实现 .sort 每个方法。我们可以称这种子类型多态性。它不同于您从泛型中获得的那种多态性,在泛型中您可以编写一个方法来处理任何类型。

在函数式编程中,通常所说的多态性是通过完全不可知数据类型来实现的,因此您可以编写单个函数 reverse::[a] -> [a]这将适用于任何可能的列表,Shapes 或 Spheres 或 Employees 或其他任何东西,更像泛型但没有运行时类型数据开销(参见 Does Haskell erase types? )。我们可以称之为参数多态性。它不同于您从类型类获得的那种多态性,在类型类中您允许多个类型具有相同的命名函数。

关于list - 为什么 Haskell 允许 Shape 列表,但不允许 Square 或 Circle 或 Triangle 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24534206/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com