【发布时间】:2012-11-20 06:47:46
【问题描述】:
让一个模块抽象Area操作(错误定义)
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]
但我认为,data Shape 和 Shape 构造函数(在 [Shape c1, ...] 和 lambda 参数上)的使用是丑陋的(我的第一个 [和糟糕的] 方式很漂亮)。
“Haskell 中的异构多态性”的正确做法是什么?
非常感谢您的宝贵时间!
【问题讨论】:
-
嗯...我正在阅读 haskell.org/haskellwiki/Existential_type ,那么
data Shape是正确的方式吗? -
像
class Surface a => Area a where area = surface一样向class Area添加一个实例怎么样?
标签: class haskell types polymorphism heterogeneous