文件夹功能:
Scanner scanner = new Scanner(new File("file.txt"));
List<String> list=new ArrayList<>();
while(scanner.hasNextLine()){
list.add(scanner.nextLine());
}
for(String str:list){
Pattern pattern = Pattern.compile("name='([^']*)'");
if(str.contains(pattern))
}
捕捉到类似的图案(左侧) 并使它们更简单(右侧)
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr func acc [] = acc
foldr func acc (x:xs) = func x (foldr func acc xs)
我注意到的一件事是,acc参数作为折叠的输入提供, 似乎恰好是该功能的中性元素/身份元素。
sum :: [Integer] -> Integer | sum :: [Integer] -> Integer
sum [] = 0 | sum [] = 0
sum (x:xs) = x + sum xs | sum (x:xs) = foldr (+) 0 xs
|
product :: [Integer] -> Integer | product :: [Integer] -> Integer
product [] = 0 | product [] = 0
product (x:xs) = x * product xs | product (x:xs) = foldr (*) 1 xs
|
concat :: [[a]] -> [a] | concat :: [[a]] -> [a]
concat [] = [] | concat [] = []
concat (x:xs) = x ++ concat xs | concat (x:xs) = foldr (++) [] xs
----------------------------------------------------------------------
not using folds | using folds
它没有任何改变,换句话说: 通过将此中性元素用作加法函数的输入,求和等于和。
In Mathematics the neutral element of the addition operation + is 0
because n + 0 = n, n ∈ ℝ
或(+) summand 0 = summand
乘法同样如此,因数和恒等式的乘积等于因特尔:
summand + 0 = summand
那么这仅仅是一个巧合,还是后面有更大的东西?
答案 0 :(得分:11)
您完全正确。我们经常希望将类似“身份”的元素传递给foldr
,以使“起点”完全不影响结果。实际上,这在Haskell中使用Monoid
类型类进行了整理。 monoid是具有标识的关联二进制运算。您提供的示例都是monoid的示例,它们都存在于Haskell中。
+
上的Num
被编码为Sum
newtype上的一个等分线。*
上的Num
被编码为Product
newtype上的一个等分线。++
都被编码为[a]
上的等分线。实际上,我们可以再走一步。折叠Monoid是一种常见的做法,我们可以使用fold
(如果需要消除歧义,也可以使用foldMap
自动进行折叠)。例如,
import Data.Foldable
import Data.Monoid
sum :: Num a => [a] -> a
sum = getSum . foldMap Sum
product :: Num a => [a] -> a
product = getProduct . foldMap Product
concat :: [[a]] -> [a]
concat = fold
如果您查看Foldable
的源代码,您会发现fold
和foldMap
实际上是根据半身像上的foldr
定义的,所以这样做与您刚才描述的完全一样。
您可以在Hackage上找到(内置)Monoid
实例的完整列表,但您可能会发现其他一些有趣的东西:
||
是与Any
newtype在一起的一个等分线。&&
是与All
newtype在一起的一个等分线。Endo
newtype(“内同化”的缩写)的类半体。作为练习,您可以考虑尝试查明每个操作的身份。