我可以使用此功能尝试在列表列表中进行“注册”匹配:
processMatch :: String -> POSIXTime -> [[(String, POSIXTime)]] -> [[(String, POSIXTime)]]
processMatch host time hostList =
case hostList of
[] -> [[(host, time)]]
((host, t):x):tail -> ((host, t):(host, time):x):tail
x:t -> x:(processMatch host time t)
此问题是使用新值而不是条件重新声明主机。因此,无论主机匹配,最终我都将其添加到第一个匹配者的列表中。 我以为我需要改用警卫,但我想不通如何在警卫中解构清单,这有可能吗?
我可以在一些条件下以另一种方式进行操作,但我很好奇是否有可能像这样简单地执行操作。 谢谢!
答案 0 :(得分:4)
我将从定义一个在host
和time
结束的助手函数开始。除此之外,您可以命名对(host, time)
,因为它将在帮助程序定义的两个不同位置使用。
助手使用case
表达式仅模式匹配内部列表的开头,而不是尝试匹配整个主机列表。
在与主机/时间对匹配的模式中,您需要使用单独的变量来捕获现有主机,然后然后将其与防护中的host
进行比较。您只能在模式中直接匹配 literals
processMatch :: String -> POSIXTime -> [[(String, POSIXTime)]] -> [[(String, POSIXTime)]]
processmatch host time lst = go lst
where newPair = (host, time)
go [] = [[newPair]]
go (head:tail) = case head of
(h,t):rest | h == host ->((h,t):newPair:rest):tail
otherwise -> head : go tail
顺便说一句,以前的输入错误使用了未定义的名称first
,该名称来自答案的先前版本中的at-pattern。也许实际上值得使用,但是我将在这里提及而不是编辑主要答案:
first@(h,_):rest | h == host -> (first:newPair:rest):tail
这完成了两件事:1)避免在两边都重复(h,t)
; 2)它避免为匹配的时间起一个名字,只要您有first
来指称配对本身,您就不会真正在意它。