查看以下版本的inits:
inits4 :: [a] -> [[a]]
inits4 [] = [[]]
inits4 (x:xs) = []:[x:ys | ys <- inits4 xs]
我知道如何工作理解列表,但这种情况太可怕了。请问有人试图解释一下吗?
答案 0 :(得分:1)
你说
inits4 :: [a] -> [[a]]
inits4 [] = [[]]
inits4 (x:xs) = []:[x:ys | ys <- inits4 xs]
我希望你能自己找出第一个案例。第二种可以机械翻译为do
符号:
inits4 (x : xs) = [] : do
ys <- inits4 xs
return (x : ys)
我们可以去除
inits4 (x : xs) =
[] : (inits4 xs >>= \ys -> return (x : ys))
我们有一项法律
m >>= \a -> return (f a) = fmap f m
所以
inits4 (x : xs) =
[] : fmap (x :) (inits4 xs)
由于inits4
会生成一个列表,fmap = map
,您应该能够完成其余的工作。
请注意,此实现存在严重的效率问题,不应在实际代码中使用。无条件渐近最优性能的最简单实现可能是
inits xs = [] : zipWith (\i _ -> take i xs) [1..] xs
答案 1 :(得分:0)
要理解递归的情况,假设我们想要计算
inits4 [x1,...,xn] =
[ [], [x1], [x1, x2], [x1, x2, x3], ..., [x1, ..., xn] ]
我们首先在列表的尾部计算inits4
。通过归纳,我们得到了
inits4 [x2,...,xn] =
[ [], [x2], [x2, x3], ..., [x2, ..., xn] ]
如何将上述内容转换为想要的结果。好吧,我们需要将x1
添加到列表列表中的每个列表中。我们可以用列表理解
[x1:y | y <- inits4 [x2,...,xn]] =
[ x1:[], x1:[x2], x1:[x2, x3], ..., x1:[x2, ..., xn] ] =
[ [x1], [x1, x2], [x1, x2, x3], ..., [x1, x2, ..., xn] ] =
这几乎是我们想要的!我们只添加添加空列表:
[] : [x1:y | y <- inits4 [x2,...,xn]] =
[ [], [x1], [x1, x2], [x1, x2, x3], ..., [x1, x2, ..., xn] ]