-1
4

2 回答 2

3

我会说首先运行以下,一一,在GHCi

:t foldr
:info foldr
:doc foldr

:t foldl
:info foldl
:doc foldl

:t map
:info map
:doc map

或者更好的是,打开hoogle.haskell.org并搜索上述每个功能,然后单击第一个链接。

但我同意 Haskell 文档很难阅读,尤其是对于初学者。我是初学者,阅读和理解它们有很多困难。

这是一个使用mapfoldr显示如何foldr工作的函数:

printFoldr xs = foldr (\x acc -> "(" ++ x ++ " + " ++ acc ++ " )") "0"  $ map  show xs

现在运行看这个:

printFoldr [1..5]
-- outputs the following:
"(1 + (2 + (3 + (4 + (5 + 0 ) ) ) ) )"

这向我们展示了如何foldr评估。在讨论如何foldr评估之前,让我们简要地看一下map.

map show [1..5]
-- outputs the following:
["1","2","3","4","5"]

这意味着map需要 2 个参数。一个列表和一个应用于列表中每个元素的函数。结果是一个新列表,其中函数应用于每个元素。因此,应用于show每个数字会输出它们的字符串表示形式。

回到foldrfoldr接受 3 个参数:

  1. 类型函数a -> b -> b
  2. 类型的初始值b
  3. 类型列表[a]

foldr获取所提供列表的每个值并将此函数应用于它。特殊之处在于 map 在每次迭代中保留函数的输出,并在下次运行时将其作为第二个参数传递给函数。因此可以方便地编写foldr如下传递的函数:(\el acc -> do something). 现在在 的下一次迭代中foldracc将保存上一次运行的值,el并将成为列表中的当前元素。BTW,acc代表累加器和el元素。这使我们能够将所提供列表的元素减少为全新的东西。

正如您在 中看到的printFoldr,初始值只是一个空字符串,但它会逐渐将列表元素添加到其中,显示它将如何将列表中的元素减少到它们的总和。

于 2021-10-08T18:31:58.830 回答
2

这是一个想法:

a1-a2+a3-a4+...
=
a1-(a2-(a3-(a4-(...(an-0)...))))

这非常适合foldr递归的模式,

foldr f z [a1,a2,a3,a4,...,an]
=
a1`f`(a2`f`(a3`f`(a4`f`(...(an`f`z)...))))

所以可以通过设置f = ...z = ...调用来编码

asum :: (Num a) => [a] -> a
asum xs = foldr f z xs
  where
  f = (...)
  z = (...)

您将需要完成此定义。


对于XOR布尔值列表的 ,假设True如果其中一个且只有一个为 ,则为TrueFalse否则,我们可以想象以下转换序列:

[ True, False, False, True, True, False, ...]
==>
[ t,    f,     f,     t,    t,    f,     ...]

其中tf是一些特别选择的数字。然后我们可以找到第二个列表的总和(不是交替总和,只是一个数字列表的总和)并检查它是否等于......一些(其他?)特殊数字,我们称之为n1

xor :: [Bool] -> Bool
xor bools  =  (aNumber ... n1)
  where
    list1 = bools
    list2 = fun1 transform list1
    transform False = f
    transform True  = t
    f = ...
    t = ...
    aNumber = sum list2
    n1 = ...
    fun1 = ...
    sum listOfNums = ...

fun1是根据上面调用的给定函数转换其参数列表中每个元素的函数transform。考虑到我们已经在使用foldr.

sum将通过使用剩下的最后一个函数来实现。

供参考,

map foo [a1,a2,a3,...,an]
=
[foo a1, foo a2, foo a3, ..., foo an]

foldl f z [a1,a2,a3,...,an]
=
((((z`f`a1)`f`a2)`f`a3)...)`f`an
于 2021-10-08T18:30:52.580 回答