假设我有一个包含各种对象坐标的类型:
type Point = (Int, Int)
data Object = A Point
| B Point
| C Point
我想创建一个检查对象重叠的函数,比如
checkOverlap:: Object -> Point -> Bool
我想只定义一个适用于所有对象的函数,而不必指定" checkOverlap(A point)(x,y)"," checkOverlap(B point)(的x,y)"等等。
我已经搜索了问题,但我能找到的唯一解决方案是添加一个中间类型,它将收集所有不同的对象,以便您可以在该类型上进行模式匹配。但是,由于这是一项家庭作业,我不允许修改大块代码以适应这种新类型。
还有其他方法吗?也许甚至没有模式匹配。看起来糟糕的编程似乎不得不多次复制相同的函数。
答案 0 :(得分:5)
如果您允许更改Object
的定义,则可以使用记录语法:
type Point = (Int, Int)
data Object = A { getPoint :: Point, ... }
| B { getPoint :: Point, ... }
| C { getPoint :: Point, ... }
checkOverlap :: Object -> Point -> Bool
checkOverlap obj pt = doSomething (getPoint obj) pt
如果您不允许更改定义并且提取点是一项常见任务,您只需添加getPoint
作为附加功能即可。如果您不想多次写case
,可以使用getPoint
:
getPoint :: Object -> Point
getPoint obj = case obj of
A pt -> pt
B pt -> pt
C pt -> pt
如果您不想要其他功能,但仍然只需要checkOverlap
的一个版本,则可以将case
移至checkOverlap
:
checkOverlap :: Object -> Point -> Bool
checkOverlap obj pt = let opt = case obj of {A a -> a; B b -> b; C c -> c}
in -- use opt and pt
答案 1 :(得分:1)
在我的评论中,这是一种使用类型类的方法:
type Point = (Int, Int)
data Obj = A Point | B Point | C Point
class HasPoint p where
point :: p -> Point
instance HasPoint (Obj) where
point (A p) = p
point (B p) = p
point (C p) = p
checkOverlap :: (HasPoint ob) => ob -> Point -> Bool
checkOverlap ob otherPoint =
undefined
where
myPoint = point ob
somethingA = checkOverlap (A (1,1)) (1,1)
somethingB = checkOverlap (B (1,1)) (1,1)
答案 2 :(得分:0)
考虑更改对象类型定义:
data ObjTy = A | B | C
data Object = Obj ObjTy Point
checkOverlap:: Object -> Point -> Bool
checkOverlap (Obj _ (x,y)) (u,v) = ...