简体   繁体   English

在Haskell中的列表上编写递归函数

[英]Writing a recursive function on lists in Haskell

I have the following question: 我有以下问题:

Define the functions 定义功能

 and, or :: [Bool] -> Bool 

which give the conjunction and disjunction of a list of Booleans. 它给出了一个布尔列表的连接和分离。 For instance, 例如,

 and [False, True] = False or [False, True] = True 

On an empty list and gives True and or gives False ; 在空列表中and给出Trueor给出False ; explain the reason for these choices. 解释这些选择的原因。

I know I can answer it but am not sure of the most efficient way to lay it out. 我知道我可以回答它,但我不确定最有效的方法来解决它。 Any help would be much appreciated. 任何帮助将非常感激。

My solution was this (but I think it could be more efficient): 我的解决方案是这样的(但我认为它可能更有效):

and, or :: [Bool] -> Bool

and []             = True
and [True, True]   = True
and [False, False] = True
and [True, False]  = False

or []             = False
or [True, True]   = False
or [False, False] = False
or [True, False]  = True

The key step you're going to have to make is to think inductively . 你必须要做的关键步骤是归纳地思考。 Your current solution: 您当前的解决方案

and :: [Bool] -> Bool

and []             = True
and [True, True]   = True
and [False, False] = True
and [True, False]  = False

enumerates some of the possibilities, but it obviously doesn't work for all lists. 列举了一些可能性,但它显然不适用于所有列表。 So how to write one that will work for lists of any length? 那么如何编写一个适用于任何长度的列表?

In Haskell, you can usually write your functions by taking apart a data type. 在Haskell中,通常可以通过拆分数据类型来编写函数。 In this case, lists. 在这种情况下,列表。 Lists are defined as: 列表定义为:

data [a] = []
         | a : [a]

So, lists have two cases: either the empty list, or a one element with a tail. 因此,列表有两种情况:空列表或带尾部的一个元素。 Let's start writing your and function then, so that it matches those two cases for lists: 让我们开始写你and函数,那么,这样它的2案件相匹配列表:

and []     = True
and (a:as) = ...

So, the "base case", the empty list, is True . 因此,“基本情况”,即空列表,为True But what should we do for the case of a list with one element, and some tail? 但是,对于包含一个元素和一些尾部的列表的情况,我们该怎么做?

Well, we already have the && function in Haskell: 好吧,我们已经在Haskell中使用了&&函数:

> True && True
True
> True && False
False
> False && True
False
> False && False
False

Interesting! 有趣! So, && takes two arguments, and correctly determines if both arguments are True. 因此, &&接受两个参数,并正确确定两个参数是否为True。 And we are currently have a list with one element, and a list for a tail. 我们目前有一个包含一个元素的列表,以及一个尾部列表。 And at the same time, we're defining the and function, that results in a single boolean value when applied to a list. 同时,我们定义了and函数,当应用于列表时会产生一个布尔值。

So we can make the inductive step and use the function we're defining, and , together with the && binary operator, to finish our definition: 因此,我们可以使用归纳步骤并使用我们定义的函数, and&&二元运算符一起完成我们的定义:

and []     = True
and (a:as) = a && (and as)

So we evaluate the tail of the list to some value (recursively), and use the && operator to combined that value with the current value, and that's our function written. 因此,我们将列表的尾部评估为某个值(递归),并使用&&运算符将该值与当前值组合,这就是我们编写的函数。

Recursion and induction, driven by the recursive structure of the lists, are the key technique to learn in programming. 由列表的递归结构驱动的递归和归纳是在编程中学习关键技术。 If you can write this, you're making a big step forward. 如果你能写出来,你就向前迈出了一大步。

I would suggest to use pattern matching to dissect the list. 我建议使用模式匹配来剖析列表。 Start with these condidtions: 从这些条件开始:

and [] = True
and (True : xs) = ...
and (False : xs) = ...

OK, for an empty list and is True . 好的,对于一个空列表andTrue If a list starts with a " True " head, how do you determinde the "truth" of the complete list? 如果列表以“ True ”头开头,您如何确定完整列表的“真实性”? Do you need a recursive call or not? 你需要递归电话吗? What if you have a " False " head? 如果你有“ False ”头怎么办?

The or case is similar, just start with or [] = False or情况类似,只是以or [] = False开头

Note that when you start with these definitions, which already pattern match on the truth values, you don't even need to use && or || 请注意,当您开始使用已经模式匹配真值的这些定义时,您甚至不需要使用&&|| .

Here are few bits from me: 以下是我的几点:

and [] = True
and (True : xs) = and xs
and (False : xs) = False

or [] = False
or (True : xs) = True
or (False : xs) = or xs

Sorry, if I have spoiled the "homework" mode of this question. 对不起,如果我破坏了这个问题的“作业”模式。

i tried to solve this with folds 我试图用折叠来解决这个问题

and = foldl (&&) True
or = foldl (||) False

this would be a simple solution to write - but i think a more abstract one and takes a [Bool] and &&s the first element of this list with the accumulator True this result will be the next accumulator to foldl with. 这将是一个简单的写入解决方案 - 但我认为是一个更抽象的解决方案,并且使用累加器将[Bool]和&& s作为此列表的第一个元素。这个结果将成为foldl的下一个累加器。

yours ε/2 你的ε/ 2

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

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