[英]Haskell foldr over infinite list, using head
f :: Int -> [[Int]] -> [[Int]]
f n acc = ([length $ head acc] ++ (take n $ repeat n)) : acc
I am trying to understand how 我试图了解如何
take 2 $ foldr f undefined [0..]
gives 给
[[2],[3,1]]
I am able to transform up to here, and then get stuck 我可以转换到此处,然后卡住
foldr f undefined [0..]
foldr f undefined ([0:[1..])
f 0 $ foldr f undefined [1..]
f 0 $ foldr f undefined (1: [2..])
f 0 $ f 1 $ foldr f undefined [2..]
f 0 $ f 1 $
You will never see anything interesting if you only expand foldr
calls. 如果仅扩展文件
foldr
调用,您将看不到任何有趣的事情。 Once a call to f
is the head of your expression, expand f
instead. 一旦调用
f
成为表达式的开头,请改为展开f
。 That expansion will require some amount of information from its acc
, which is the trailing foldr
call, but it won't need all of it, so you'll be able to make progress. 该扩展将需要从
acc
后面的foldr
调用中获取一些信息,但并不需要全部 ,因此您将能够取得进步。
...
f 0 $
([length $ head (foldr f undefined [1..])] ++ (take 0 $ repeat 0)) : foldr f undefined [1..]
...
Here I've repeated foldr f undefined [1..]
twice because acc
is used twice, but of course you need only expand it once, using the same result in both places. 在这里,由于
acc
被使用了两次,所以重复了foldr f undefined [1..]
两次,但是您当然只需要扩展一次,就可以在两个地方使用相同的结果。
From f 0 $ f 1 $ foldr f undefined [2..]
, continue for one more iteration, then simply inline the definition of f
: 从
f 0 $ f 1 $ foldr f undefined [2..]
,继续进行一次迭代,然后简单地内联f
的定义:
f 0 $ f 1 $ foldr f undefined [2..]
f 0 $ f 1 $ f 2 $ foldr f undefined [3..] -- below let rest = foldr f undefined [3..]
f 0 $ f 1 $ f 2 $ rest
f 0 $ f 1 $ (\n acc -> ([length $ head acc] ++ (take n $ repeat n)) : acc) 2 $ rest
f 0 $ f 1 $ (([length $ head rest] ++ (take 2 $ repeat 2)) : rest)
f 0 $ f 1 $ (([length $ head rest] ++ [2,2]) : rest)
f 0 $ f 1 $ ([length $ head rest,2,2] : rest)
f 0 $ (\n acc -> ([length $ head acc] ++ (take n $ repeat n)) : acc) 1 $ ([length $ head rest,2,2] : rest)
f 0 $ (([length $ head ([length $ head rest,2,2] : rest)] ++ (take 1 $ repeat 1)) : [length $ head rest,2,2] : rest)
f 0 $ (([length $ [length $ head rest,2,2]] ++ [1]) : [length $ head rest,2,2] : rest)
-- this is the crux, we don't need to evaluate rest to evaluate the length here
f 0 $ (([3] ++ [1]) : [length $ head rest,2,2] : rest)
f 0 $ ([3,1] : [length $ head rest,2,2] : rest)
((\n acc -> ([length $ head acc] ++ (take n $ repeat n)) : acc) 0 $ ([3,1] : [length $ head rest,2,2] : rest)
([length $ head ([3,1] : [length $ head rest,2,2] : rest)] ++ (take 0 $ repeat 0)) : [3,1] : [length $ head rest,2,2] : rest
([length $ [3,1]] ++ []) : [3,1] : [length $ head rest,2,2] : rest
[length $ [3,1]] : [3,1] : [length $ head rest,2,2] : rest
[2] : [3,1] : [length $ head rest,2,2] : rest
Now since we only want the first two element ( take 2
), we get 现在,由于我们只想要前两个元素(
take 2
),我们得到
[[2],[3,1]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.