重用多个值构造函数模式匹配时,避免重复代码

ely*_*ely 5 haskell

假设您有一个包含多个值构造函数的LogMessage数据结构,例如像这样的数据结构:

data LogMessage = Unknown String 
                | LogMessage MessageType TimeStamp String
Run Code Online (Sandbox Code Playgroud)

如果消息可以正确解析,它有一些额外的数据然后a String.如果它无法解析,那么它只是一个全能Unknown String.

或者假设你正在使用类似的东西Either String String,以便你可能正在处理一个Left String或一个Right String.

现在假设您希望将相同的处理步骤应用于基础数据,而不管它驻留在哪个值构造函数中.

例如,我可能想要检测LogMessage字符串中的某个单词,所以我可以使用这样的函数:

detectWord :: String -> LogMessage -> Bool
detectWord s (Unknown m)         = isInfixOf s (map toLower m)
detectWord s (LogMessage _  _ m) = isInfixOf s (map toLower m)
Run Code Online (Sandbox Code Playgroud)

或者它可以很容易地编写Either String String为输入而不是LogMessage.

在这两种情况下,我都必须重复完全相同的代码(isInfixOf ...部分),因为由于不同值构造函数上的模式匹配,我必须提取它将以不同方式操作的基础数据.

对于每个不同的值构造函数匹配,必须重复/"复制 - 粘贴"代码是很糟糕的.

如何在没有复制/粘贴代码的情况下编写这些类型的Haskell函数?我怎样才能编写底层逻辑一次,然后解释如何在许多不同的值构造函数模式中使用它?

简单地将其移动到辅助辅助函数会减少字符数,但并不能真正解决问题.例如,下面的想法在实质上没有比第一种情况更好的"不重复自己":

helper :: String -> String -> Bool
helper s m = isInfixOf s (map toLower m)

detectWord :: String -> LogMessage -> Bool
detectWord s (Unknown m)        = helper s m
detectWord s (LogMessage _ _ m) = helper s m
Run Code Online (Sandbox Code Playgroud)

我们不得不对每种不同的模式说同样的话.

com*_*orm 6

编写一个在任何一种情况下都能获取消息的函数.然后,您不需要为不关心的用途编写单独的案例:

getMsg (Unknown m) = m
getMsg (LogMessage _ _ m) = m

detectWord s log = infixOf s (map toLower (getMsg log))
Run Code Online (Sandbox Code Playgroud)

请注意,某些东西必须检查您的类型的情况,并且getMsg与它们沿着这些线路一样小.