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
,是给定标准的最佳和最自然的解决方案(我倾向于远离总和类型的记录)。