我很好奇是否可以使用列表推导代替递归来实现以下示例。
接受元素和列表的函数replaceFirst
,并替换列表中第一次出现的元素。
这可以使用递归来完成,如下所示:
replaceFirst _ [] = []
replaceFirst elem y (x:xs) | x==y = (elem:xs)
| otherwise = x:replaceFirst elem y xs
我的问题是,这个递归函数,或者在列表中第一次出现元素时运行的类似递归函数,是否可以用列表推导函数替换?为什么或者为什么不? (我更关心的是推理而不是实际的代码)。
答案 0 :(得分:8)
对于各种形式的map
,filter,
和concatMap
,列表理解为syntactic sugar。如果您的递归函数可以用这些来描述,那么您可以将其重写为列表解析。它们不能像你上面那样短路,也不能通过累积状态。
你的replaceFirst
似乎需要一个累加器来“告诉”列表中后面的元素有关早期元素的外观。我认为这很难或不可能只使用列表推导语法编写。
答案 1 :(得分:0)
列表理解,受左撇子启发:
replaceFirst elem y xs = [a | let b = break (==y) xs
c = if not (null $ snd b)
then fst b ++ [elem] ++ tail (snd b)
else fst b
, a <- c]