Jav*_*ell 2 haskell list fold function-definition
在某些情况下,我不明白在函数中如何使用foldr和foldl使用。
这是几个例子,然后我解释为什么我不理解它们:
-- Two implementation of filter and map
map' f = foldr (\x acc -> (f x):acc) []
map'' f xs = foldl (\acc x -> acc ++ [(f x)]) [] xs
filter' f xs = foldr(\x acc -> if(f x) then x:acc else acc) [] xs
filter'' f = foldl(\acc x -> if(f x) then acc++[x] else acc) []
Run Code Online (Sandbox Code Playgroud)
为什么map''使用xsbut non map'?map'列表理解公式也不需要列表吗?
filter'vs 的情况相同filter''。
这是一个按排序顺序插入元素的实现:
insert e [] = [e]
insert e (x:xs)
| e > x = x: insert e xs
| otherwise = e:x:xs
sortInsertion xs = foldr insert [] xs
sortInsertion'' xs = foldl (flip insert) [] xs
Run Code Online (Sandbox Code Playgroud)
为什么insert在sortInsertion( [] xs) (空列表和列表)中翻转的参数与 insert(e []) (元素和空列表)的定义相比
为什么
map''使用xsbut nonmap'?map'列表理解公式也不需要列表吗?filter'vs 的情况相同filter''。
这称为“eta-reduction”,它是一种省略冗余参数名称的常用方法(“point-free style”)。基本上只要你有一个函数,它的主体只是一个函数对其参数的应用,你可以减少参数:
add :: Int -> Int -> Int
add x y = x + y
-- “To add x and y, call (+) on x and y.”
add :: (Int) -> (Int) -> (Int)
add x y = ((+) x) y
-- “To add x, call (+) on x.”
add :: (Int) -> (Int -> Int)
add x = (+) x
-- “To add, call (+).”
add :: (Int -> Int -> Int)
add = (+)
Run Code Online (Sandbox Code Playgroud)
更准确地说,如果你有f x = g xwherex没有出现在 中g,那么你可以写f = g.
一个常见的错误是想知道为什么f x = g . h x不能写为f = g . h. 它不符合模式,因为(.)运算符是 的主体中的顶级表达式f:它实际上是f x = (.) g (h x)。您可以将其编写为f x = (((.) g) . h) x,然后将其缩减为f = (.) g . h或f = fmap g . h使用Functor实例 for ->,但这不被认为是非常易读的。
为什么插入的参数被翻转
sortInsertion
的功能参数foldr和foldl具有不同的参数顺序:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
Run Code Online (Sandbox Code Playgroud)
或者,使用更详细的类型变量名称:
foldr
:: (Foldable container)
=> (element -> accumulator -> accumulator)
-> accumulator -> container element -> accumulator
foldl
:: (Foldable container)
=> (accumulator -> element -> accumulator)
-> accumulator -> container element -> accumulator
Run Code Online (Sandbox Code Playgroud)
这只是折叠关联方向的助记符:
foldr f z [a, b, c, d]
==
f a (f b (f c (f d z))) -- accumulator on the right (second argument)
foldl f z [a, b, c, d]
==
f (f (f (f z a) b) c) d -- accumulator on the left (first argument)
Run Code Online (Sandbox Code Playgroud)
那就是偏函数应用。
map' f = foldr (\x acc -> (f x):acc) []
Run Code Online (Sandbox Code Playgroud)
就是一样
map' f xs = foldr (\x acc -> (f x):acc) [] xs
Run Code Online (Sandbox Code Playgroud)
如果xs两边都省略。
然而,除了这个解释,我认为你需要一本 Haskell 的初学者书籍。考虑一下LYAH。