根据值类型执行不同的功能

时间:2016-05-19 13:26:42

标签: haskell

我希望能够将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。如何在不收到警告的情况下获得相同的功能?

2 个答案:

答案 0 :(得分:4)

冗余模式匹配是:

applyAction _ _ = Nothing

Thing只定义了两个构造函数BoxValBallVal,并且在前两个模式匹配中都明确处理了这些构造函数:

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根据其第一个参数的类型做正确的事。)