Haskell中类型的模式匹配
假设我有一个包含各种对象坐标的类型,定义为:Haskell中类型的模式匹配,haskell,types,pattern-matching,Haskell,Types,Pattern Matching,假设我有一个包含各种对象坐标的类型,定义为: type Point = (Int, Int) data Object = A Point | B Point | C Point 我想创建一个函数来检查对象的重叠,如下所示 checkOverlap:: Object -> Point -> Bool 我只想定义一个适用于所有对象的函数,而不必指定“checkOverlap(A点)(x,y)”、“chec
type Point = (Int, Int)
data Object = A Point
| B Point
| C Point
我想创建一个函数来检查对象的重叠,如下所示
checkOverlap:: Object -> Point -> Bool
我只想定义一个适用于所有对象的函数,而不必指定“checkOverlap(A点)(x,y)”、“checkOverlap(B点)(x,y)”等等
我已经用谷歌搜索了这个问题,但我能找到的唯一解决方案是添加一个中间类型,它将收集所有不同的对象,以便您可以对该类型进行模式匹配。然而,由于这是一个家庭作业,我不允许修改大块代码来适应这种新类型
还有别的办法吗?也许连模式匹配都不行。似乎糟糕的编程必须多次复制同一个函数。如果允许更改
对象的定义,则可以使用记录语法:
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
作为附加函数。如果您不想多次写入getPoint
,可以使用case
:
getPoint :: Object -> Point
getPoint obj = case obj of
A pt -> pt
B pt -> pt
C pt -> pt
如果您不需要附加功能,但仍然只需要一个版本的checkOverlap
,则可以将案例
移动到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
如果允许更改对象的定义,则可以使用记录语法:
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
作为附加函数。如果您不想多次写入getPoint
,可以使用case
:
getPoint :: Object -> Point
getPoint obj = case obj of
A pt -> pt
B pt -> pt
C pt -> pt
如果您不需要附加功能,但仍然只需要一个版本的checkOverlap
,则可以将案例
移动到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
考虑更改对象类型定义:
data ObjTy = A | B | C
data Object = Obj ObjTy Point
checkOverlap:: Object -> Point -> Bool
checkOverlap (Obj _ (x,y)) (u,v) = ...
考虑更改对象类型定义:
data ObjTy = A | B | C
data Object = Obj ObjTy Point
checkOverlap:: Object -> Point -> Bool
checkOverlap (Obj _ (x,y)) (u,v) = ...
在我的评论中,TypeClass有一种方法:
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)
在我的评论中,TypeClass有一种方法:
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)
您想要使用类型类;然后将“点”列表关联到每个对象;然后为每个对象定义该类型类的实例,然后您的checkOverlap
函数可以使用类型约束,例如:checkOverlap::(HasPoints ob)=>obj->Point->Bool
;然后将“点”列表关联到每个对象;然后为每个对象定义这个类型类的实例,然后您的checkOverlap
函数可以使用类型约束,比如:checkOverlap::(HasPoints ob)=>obj->Point->Bool
。可能不允许:“但是,由于这是一个家庭作业,我不允许修改大块代码来适应这个新类型。”可能不允许:“但是,由于这是一个家庭作业练习,我不允许修改大块代码以适应这种新类型。”这里的typeclass完全没有意义,您只是为Obj定义它,所以为什么不直接做point::Obj->point
?这里的typeclass完全没有意义,您只是为Obj定义它,那么为什么不直接做点呢?我认为模式匹配定义的getPoint
,是给定标准的最佳和最自然的解决方案(我倾向于远离总和类型的记录)。我认为模式匹配定义的getPoint
,是给定标准的最佳和最自然的解决方案(我倾向于远离总和类型的记录)。