gpt4 book ai didi

haskell - 类型类和模块如何交互?

转载 作者:行者123 更新时间:2023-12-05 00:06:26 26 4
gpt4 key购买 nike

为了掌握更好的类型类(几乎从零开始),我尝试使用面积计算对二维形状进行建模,如下所示:

module TwoDShapes where

class TwoDShape s where
area :: s -> Float

data Circle = Circle Float deriving Show
aCircle radius | radius < 0 = error "circle radius must be non-negative"
| otherwise = Circle radius
instance TwoDShape Circle where
area (Circle radius) = pi * radius * radius

data Ellipse = Ellipse Float Float deriving Show
anEllipse axis_a axis_b | axis_a < 0 || axis_b < 0 = error "ellipse axis length must be non-negative"
| otherwise = Ellipse axis_a axis_b
instance TwoDShape Ellipse where
area (Ellipse axis_a axis_b) = pi * axis_a * axis_b

其他类型的形状依此类推。

这很好,但我想试试这个:
module TwoDShapes  where

class TwoDShape s where
area :: s -> Float

data TwoDShapeParams = TwoDShapeParams Float Float Float deriving Show

instance TwoDShape TwoDShapeParams where
area (TwoDShapeParams length_a length_b constant) = foldl (*) 1 [length_a, length_b, constant]

aCircle radius | radius < 0 = error "circle radius must be non-negative"
| otherwise = TwoDShapeParams radius radius pi

anEllipse axis_a axis_b | axis_a < 0 || axis_b < 0 = error "ellipse axis length must be non-negative"
| otherwise = TwoDShapeParams axis_a axis_b pi

等等,这也很好。为了隐藏信息,我将模块声明更改为如下所示:
module TwoDShapes (TwoDShape, area, aCircle, anEllipse, aRectangle, aTriangle)

令我惊讶的是,这 1) 工作和 2) 在 ghci aCircle 中计算结果为 TwoDShapeParams 1.0 1.0 3.1415927这是真的,但我不明白类型 TwoDShapeParams在模块外可见。我不确定我在期待什么,但不是这个。

我真正想要的是类型类、它的方法和“智能构造函数”在模块外部可见,没有别的。可以这样做吗?

最佳答案

虽然 TwoDShapes 的表示已隐藏,您已导出 Show例如,它允许 TwoDShapes 类型的任意值转换为 String ,所以这就是信息泄露的来源。真正的抽象类型不应定义 Show例如,或者实际上是 Data类似地暴露有关表示的信息的实例。有一种方法可以将您的类型转换为 String ,只要 String是独立于表示的(参见 ShowData.Map.MapData.Array.Array 实例以获取很好的示例)。

请注意,模块系统正在发挥作用:您仍然不能引用 TwoDShapes定义它的模块之外的构造函数。

关于haskell - 类型类和模块如何交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3227891/

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