类型和模块如何交互?

kei*_*thb 4 haskell visibility module typeclass

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

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
Run Code Online (Sandbox Code Playgroud)

等等其他形状.

这很好,但我想到尝试这个:

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
Run Code Online (Sandbox Code Playgroud)

等等也没关系.以信息隐藏为目标,我将模块声明更改为如下所示:

module TwoDShapes (TwoDShape, area, aCircle, anEllipse, aRectangle, aTriangle)
Run Code Online (Sandbox Code Playgroud)

并且稍微令我惊讶的是1)工作和2)在ghci aCircle 评估TwoDShapeParams 1.0 1.0 3.1415927哪个是真的但我不明白该类型TwoDShapeParams在模块外是如何可见的.我不确定我在期待什么,但不是这个.

我真正喜欢的是类型类,它的方法和"智能构造函数"在模块外部可见而没有别的.可以这样做吗?

Sim*_*low 6

尽管TwoDShapes隐藏了表示,但您已Show为其派生了一个实例,它允许将任意类型的值TwoDShapes转换为a String,因此这是信息泄漏的来源.真正的抽象类型不应该定义Show实例,或者实际上是一个Data类似地公开有关表示的信息的实例.有一种方法可以将类型转换为a String,只要它与String表示无关(请参阅Show实例Data.Map.Map以及Data.Array.Array此示例).

请注意,模块系统正在完成其工作:您仍然无法引用TwoDShapes定义它的模块之外的构造函数.