And*_*rdo 5 haskell fold zipwith
我是Haskell的新手,并且遇到了以下使我感到困惑的代码:
foldr (zipWith (:)) (repeat []) [[1,2,3],[4,5,6],[7,8,9,10]]
Run Code Online (Sandbox Code Playgroud)
它产生以下结果,在反复试验之后,我不完全确定为什么:
[[1,4,7],[2,5,8],[3,6,9]]
Run Code Online (Sandbox Code Playgroud)
我的印象是,(:)
将项目添加到列表中,并(repeat [])
产生无数的空列表[]
,并foldr
接受一个函数,一个项目和一个列表,并通过将函数连续应用于列表中的每个项目来压缩列表。列出结果。
也就是说,我直观地理解以下代码如何产生结果10:
foldr (+) 1 [2,3,4]
Run Code Online (Sandbox Code Playgroud)
但是,我完全不确定为什么要使用foldr (zipWith (:)) (repeat [])
一个列表列表并生成另一个列表列表,这些列表中的项按其原始内部索引分组。
任何解释都是有启发性的。
这很简单。foldr
被定义为
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Run Code Online (Sandbox Code Playgroud)
从而,
foldr f z [a,b,c,...,n] = f a (f b (f c (...(f n z)...)))
Run Code Online (Sandbox Code Playgroud)
或者在这里
foldr (zipWith (:)) (repeat []) [[1,2,3],[4,5,6],[7,8,9,10]]
=
zipWith (:) [1,2,3]
( foldr (zipWith (:)) (repeat []) [[4,5,6],[7,8,9,10]] )
=
...
=
zipWith (:) [1,2,3]
( zipWith (:) [4,5,6]
( zipWith (:) [7,8,9,10]
( foldr (zipWith (:)) (repeat []) [] )))
=
zipWith (:) [1,2,3]
( zipWith (:) [4,5,6]
( zipWith (:) [7,8,9,10]
( repeat [] )))
=
zipWith (:) [1,2,3]
( zipWith (:) [4,5,6]
( zipWith (:) [ 7, 8, 9,10]
[[],[],[],[],[],[],....] ))
=
zipWith (:) [1,2,3]
( zipWith (:) [ 4, 5, 6 ]
[[7],[8],[9],[10]] )
=
zipWith (:) [ 1 , 2 , 3 ]
[[4,7],[5,8],[6,9]]
Run Code Online (Sandbox Code Playgroud)
就是这样。
(菜单上的下一步,traverse ZipList [[1,2,3],[4,5,6],[7,8,9,10]]
... :)或以后。)
至于另一个例子,是
foldr (+) 1 [2,3,4]
= 2 + foldr (+) 1 [3,4]
= 2 + (3 + foldr (+) 1 [4])
= 2 + (3 + (4 + foldr (+) 1 []))
= 2 + (3 + (4 + 1))
= 2 + (3 + 5)
= 2 + 8
= 10
Run Code Online (Sandbox Code Playgroud)
因为+
是严格在它的两个参数。
zipWith
在两个参数中都不严格,也不是(:)
,因此第一个序列应仅用作说明。实际强制将以自上而下的顺序而不是自下而上的顺序发生。例如,
> map (take 1) . take 1 $ zipWith (:) (1 : undefined) (repeat undefined)
[[1]]
Run Code Online (Sandbox Code Playgroud)
完全符合
map (take 1) . take 1 $ zipWith (:) (1 : undefined) (repeat undefined)
=
map (take 1) . take 1 $ zipWith (:) (1 : undefined) (undefined : repeat undefined)
=
map (take 1) . take 1 $ (1 : undefined) : zipWith (:) undefined (repeat undefined)
=
map (take 1) $ (1 : undefined) : take 0 (zipWith (:) undefined (repeat undefined))
=
map (take 1) $ (1 : undefined) : []
=
map (take 1) [(1 : undefined)]
=
[take 1 (1 : undefined)]
=
[1 : take 0 undefined]
=
[1 : []]
=
[[1]]
Run Code Online (Sandbox Code Playgroud)