简体   繁体   English

Haskell 函数(地图、文件夹、文件夹)

[英]Haskell Functions (map,foldr, foldl)

I am struggling to think of a way to utilize these functions for this beginner level coding class that I am taking to learn functional programming in Haskell. The functions I have to write are shown below, asum is supposed to turn a list of integers [a1,a2,..,an] into the alternating sum a1-a2+a3-a4+.… and I am not sure how to approach it with these functions.我正在努力想办法将这些函数用于这个初学者级别的编码 class,我将在 Haskell 中学习函数式编程。我必须编写的函数如下所示, asum应该转换整数列表[a1,a2,..,an]转换为交替和a1-a2+a3-a4+.…我不确定如何使用这些函数来处理它。 The xor function is supposed to that computes the XOR of a list of Booleans. xor function 应该计算布尔值列表的 XOR。 I need some help to understand how to use these functions and it would greatly appreciated.我需要一些帮助来了解如何使用这些功能,我将不胜感激。 I am also new to Haskell so any explanations would help.我也是 Haskell 的新手,所以任何解释都会有所帮助。 Thanks I have to use map foldr foldl .谢谢我必须使用map foldr foldl

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

xor :: [Bool] -> Bool

I would say start by running the following, one by one, in GHCi :我会说首先在GHCi中逐一运行以下命令:

:t foldr
:info foldr
:doc foldr

:t foldl
:info foldl
:doc foldl

:t map
:info map
:doc map

Or better, open hoogle.haskell.org and search each of the above mentioned functions and click on the first link.或者更好,打开hoogle.haskell.org并搜索上述每个功能,然后单击第一个链接。

But I agree that Haskell documentation are difficult to read, especially for beginners.但我同意 Haskell 文档很难阅读,尤其是对于初学者。 I'm a beginner and I have a lot of difficulty reading and understanding them.我是初学者,阅读和理解它们有很多困难。

Here's a function that uses map and foldr to show how foldr works:这是一个 function,它使用mapfoldr来展示foldr的工作原理:

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

Now running watch this:现在运行看这个:

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

This shows us how foldr is evaluated.这向我们展示了如何评估foldr Before going into how foldr is evaluated, let's look briefly at map .在讨论如何评估foldr之前,让我们简要地看一下map

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

This means that map takes 2 arguments. A list and a function that is applied to each element of the list.这意味着map需要 2 个 arguments. 列表和一个应用于列表每个元素的 function。 The result is a new list with the function applied to each element.结果是一个新列表,每个元素都应用了 function。 Thus, applying show to each number outputs their string representation.因此,将show应用于每个数字会输出它们的字符串表示形式。

Back to foldr .返回foldr foldr takes 3 arguments: foldr需要 3 arguments:

  1. a function of type a -> b -> b a function 类型a -> b -> b
  2. an initial value of type b类型b的初始值
  3. a list of type [a] [a]类型的列表

foldr takes each and every value of the provided list and applies this function to it. foldr获取所提供列表的每个值并将此 function 应用于它。 What is special is that map retains the output of the function over each iteration and passes it to the function as its second argument on the next run.特别之处在于 map 在每次迭代中保留 function 的 output,并在下一次运行时将其作为第二个参数传递给 function。 Therefore it is convenient to write the function that is passed foldr as follows: (\el acc -> do something) .因此,将传递给foldr的 function 编写如下很方便: (\el acc -> do something) Now on the next iteration of foldr , acc will hold the value of the previous run and el will be the current element from the list.现在在foldr的下一次迭代中, acc将保留上一次运行的值,而el将是列表中的当前元素。 BTW, acc stands for accumulator and el for element.顺便说一句, acc代表累加器, el代表元素。 This enables us to reduce elements of the provided list to something completely new.这使我们能够将提供的列表的元素减少为全新的东西。

As you can see in printFoldr , the initial value is just an empty string but it gradually adds the lists elements to it showing how it would have reduced the elements of the list to their sum.正如您在printFoldr中看到的,初始值只是一个空字符串,但它逐渐向其中添加列表元素,显示它将如何将列表元素减少到它们的总和。

Here's an idea:这是一个想法:

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

This fits pretty well to the foldr pattern of recursion,这非常适合递归的foldr模式,

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

So it can be coded by setting f =... and z =... and calling所以它可以通过设置f =...z =...并调用来编码

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

You will need to complete this definition.您将需要完成此定义。


For the XOR of a list of Booleans, assuming it is to be True if one and only one of them is True , and False otherwise, we can imagine this sequence of transformations:对于布尔值列表的XOR ,假设只有其中一个为True则为True ,否则为False ,我们可以想象以下转换序列:

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

where t and f are some specially chosen numbers.其中tf是一些特别选择的数字。 And then we can find the sum of this second list (not alternating sum, just a sum of a list of numbers) and check whether it is equal to... some (other?) special number, let's call it n1 :然后我们可以找到第二个列表的总和(不是交替总和,只是数字列表的总和)并检查它是否等于......一些(其他?)特殊数字,我们称之为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 is the function which transforms each element of its argument list according to the given function, called transform above. fun1是 function,它根据给定的 function 转换其参数列表的每个元素,在上面称为transform It is one of the two functions left from the three you were given, considering we've already been using foldr .考虑到我们已经在使用foldr ,它是您获得的三个功能中剩下的两个功能之一。

sum is to be implemented by using the last function that's left. sum将通过使用剩下的最后一个 function 来实现。

FYI,供参考,

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

and

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM