让一个模块来抽象区域
操作(糟糕的定义)
将一个模块用来抽象
区域
操作(定义不好)。class Area someShapeType where
area :: someShapeType -> Float
-- module utilities
sumAreas :: Area someShapeType => [someShapeType]
sumAreas = sum . map area
让后验明确形状类型模块(好或可接受的定义)
data Point = Point Float Float
data Circle = Circle Point Float
instance Surface Circle where
surface (Circle _ r) = 2 * pi * r
data Rectangle = Rectangle Point Point
instance Surface Rectangle where
surface (Rectangle (Point x1 y1) (Point x2 y2)) = abs $ (x2 - x1) * (y2 - y1)
让一些数据
c1 = Circle (Point 0 0) 1
r1 = Rectangle (Point 0 0) (Point 1 1)
然后,尝试使用
totalArea = sumAreas [c1, r1]
必须将 [c1, r1]
类型扩展为 [Circle]
或者 [Rectangle]
!(并且不合法)
我可以使用 forall
和额外的 data
类型来实现这个目标。
data Shape = forall a . Surface a => Shape a
sumSurfaces :: [Shape] -> Float
sumSurfaces = sum . map (\(Shape x) -> surface x)
然后,接下来的代码成功运行。
sumSurfaces [Shape c1, Shape r1]
我认为,在[Shape c1, ...]
和lambda参数中使用data Shape
和Shape
构造函数是不美观的(我的第一种[且不好的]方法比较美观)。
在Haskell中实现"异质多态"的正确方式是什么?
非常感谢您的时间!
class Area
中添加一个实例,像这样class Surface a => Area a where area = surface
? - ErikR