我希望能够将Action
应用于Thing
,其中只有一些事情可以接受某些操作。
data Thing = BoxVal Box | BallVal Ball deriving (Show)
data Box = Box {name :: String} deriving (Show)
data Ball = Ball {size :: Int} deriving (Show)
data Action = SetName String | Resize Int | ToFoo deriving (Show)
applyAction :: Thing -> Action -> Maybe String
applyAction (BoxVal box) a = actionToBox box a
applyAction (BallVal ball) a = undefined
applyAction _ _ = Nothing
actionToBox :: Box -> Action -> Maybe String
actionToBox b (SetName s) = Just $ s
actionToBox b (ToFoo) = Just "foo"
actionToBox _ _ = Nothing
上面的代码有效(并不是很优雅),但GHCI在Pattern match(es) are overlapped
中抱怨applyAction
。如何在不收到警告的情况下获得相同的功能?
答案 0 :(得分:4)
冗余模式匹配是:
applyAction _ _ = Nothing
Thing
只定义了两个构造函数BoxVal
和BallVal
,并且在前两个模式匹配中都明确处理了这些构造函数:
applyAction (BoxVal box) a = actionToBox box a
applyAction (BallVal ball) a = undefined
这使得applyAction _ _
变得不必要了。它永远不会匹配,因为前两个模式匹配所有可能性。
答案 1 :(得分:2)
为applyAction
定义一个类,然后定义适当的实例。
data Thing = BoxVal Box | BallVal Ball deriving (Show)
data Box = Box {name :: String} deriving (Show)
data Ball = Ball {size :: Int} deriving (Show)
data Action = SetName String | Resize Int | ToFoo deriving (Show)
class Actionable x where
applyAction :: x -> Action -> Maybe String
instance Actionable Box where
applyAction :: Box -> Action -> Maybe String
applyAction b (SetName s) = Just s
applyAction b ToFoo = Just "foo"
applyAction _ _ = Nothing
instance Actionable Thing where
applyAction :: Thing -> Action -> Maybe String
applyAction (BoxVal b) a = applyAction b a
applyAction _ _ = undefined
(该类不直接解决重叠模式问题,但确实可以避免您需要提出新的函数名称。applyAction
根据其第一个参数的类型做正确的事。)