Haskell Functions (map,foldr, foldl)



我正在努力想一种方法,将这些函数用于我正在Haskell中学习函数编程的初级编码课程。我必须编写的函数如下所示,asum应该将整数列表[a1,a2,..,an]转换为交替和a1-a2+a3-a4+.…,我不知道如何使用这些函数。xor函数应该计算布尔值列表的XOR。我需要一些帮助来了解如何使用这些功能,我们将不胜感激。我也是哈斯克尔的新手,所以任何解释都会有所帮助。谢谢,我必须使用map foldr foldl

asum :: (Num a) => [a] -> a
xor :: [Bool] -> Bool

我想说,首先在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. CCD_ 18类型的初始值
  3. 类型为[a]的列表

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

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

这里有一个想法:

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,则假设为True,否则为False,我们可以想象以下转换序列:

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

其中CCD_ 36和CCD_。然后我们可以找到第二个列表的和(不是交替和,只是一个数字列表的和),并检查它是否等于。。。一些(其他?)特殊号码,让我们称之为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将通过使用剩下的最后一个函数来实现。

FYI,

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

最新更新