文件夹功能的“累积参数”的标识

时间:2018-07-31 15:52:56

标签: haskell

文件夹功能:

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

那么这仅仅是一个巧合,还是后面有更大的东西?

1 个答案:

答案 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的源代码,您会发现foldfoldMap实际上是根据半身像上的foldr定义的,所以这样做与您刚才描述的完全一样。

您可以在Hackage上找到(内置)Monoid实例的完整列表,但您可能会发现其他一些有趣的东西:

    布尔值上的
  • ||是与Any newtype在一起的一个等分线。
  • 布尔值上的
  • &&是与All newtype在一起的一个等分线。
  • 函数组成是带有Endo newtype(“内同化”的缩写)的类半体。

作为练习,您可以考虑尝试查明每个操作的身份。