你可以不用数字来完成这个任务。让我们一步步来实现它。我们将使用累加器方法,但是累加器中不再保存一个数字,而是保存一个函数,该函数重复其参数特定的次数。
test0 :: [a] -> [a]
test0 xs = go rep1 xs
where
rep1 :: a -> [a]
rep1 a = [a]
go :: (a -> [a]) -> [a] -> [a]
go _rep [] = []
go rep (a : as) = rep a ++ go (oneMore rep) as
oneMore :: (a -> [a]) -> (a -> [a])
oneMore rep a = a : rep a
我们从使用
rep1
这个非常简单的函数开始调用
go
,它将其参数转换为一个单例列表。然后在每次递归调用中,我们通过使重复器函数重复其参数一次来修改重复器函数。
test0
可以正常工作,但它使用了
++
函数,而您不应该使用任何预定义函数。在这里使用
++
也意味着您必须构建小列表并将它们放在一起,这是我们可以很容易地消除的低效率。
请注意,每次
go
调用
rep
时,它立即将其他内容附加到结果中。这提示了解决方案:与其让
rep
接收一个元素并生成一个列表,不如让它接收一个元素和一个列表,并生成由元素重复若干次后跟给定列表组成的列表!所以我们会有
rep1 "a" ["b", "c"] = ["a", "b", "c"]
rep2 "a" ["b", "c"] = ["a", "a", "b", "c"]
其中rep1
和rep2
是前两个rep
函数。只需要做出一些调整。
test :: [a] -> [a]
test = go rep1
where
rep1 :: a -> [a] -> [a]
rep1 a as = a : as
go :: (a -> [a] -> [a]) -> [a] -> [a]
go _ [] = []
go rep (a : as) = rep a (go (oneMore rep) as)
oneMore :: (a -> [a] -> [a])
-> a -> [a] -> [a]
oneMore f a as = a : f a as
这真的不是解决问题的一种
高效方式,但它是一种相当极简主义的方法。
zip
。 - 4castle