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

时间:2011-05-09 04:56:54

标签: list haskell recursion functional-programming

我有以下问题:

  

定义功能

and, or :: [Bool] -> Bool
     

给出了布尔列表的连接和分离。例如,

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

在空列表and上提供Trueor提供False;解释这些选择的原因。

我知道我可以回答它但不确定最有效的解决方法。任何帮助将不胜感激。

我的解决方案是这样的(但我认为它可能更有效):

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

4 个答案:

答案 0 :(得分:8)

您必须做的关键步骤是归纳。您当前的解决方案:

and :: [Bool] -> Bool

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

列举了一些可能性,但它显然不适用于所有列表。那么如何编写一个适用于任何长度列表的文件?

在Haskell中,您通常可以通过拆分数据类型来编写函数。在这种情况下,列表。列表定义为:

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

因此,列表有两种情况:空列表或带尾部的一个元素。让我们开始编写and函数,以便它匹配列表的这两种情况:

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

因此,“基本案例”,即空列表,是True。但是,对于包含一个元素的列表以及一些尾部,我们应该怎么办?

好吧,我们已经在Haskell中拥有&&函数:

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

有趣!因此,&&接受两个参数,并正确确定两个参数是否为True。我们目前有一个包含一个元素的列表,以及一个尾部列表。同时,我们定义了and函数,当应用于列表时会产生一个布尔值。

所以我们可以使归纳步骤并使用我们定义的函数and&&二元运算符来完成我们的定义:

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

因此我们将列表的尾部评估为某个值(递归),并使用&&运算符将值与当前值组合在一起,这就是我们编写的函数。< / p>

由列表的递归结构驱动的递归和归纳是在编程中学习的 关键技术。如果你能写出这个,你就向前迈出了一大步。

答案 1 :(得分:8)

我建议使用模式匹配来剖析列表。从这些条件开始:

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

好的,对于空列表andTrue。如果列表以“True”头开头,您如何确定完整列表的“真实性”?你需要递归电话吗?如果你有一个“False”头怎么办?

or案例类似,只是从or [] = False

开始

请注意,当您开始使用这些已经与真值相匹配的定义时,您甚至不需要使用&&||

答案 2 :(得分:1)

以下是我的一些内容:

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

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

很抱歉,如果我破坏了这个问题的“作业”模式。

答案 3 :(得分:0)

我试图用折叠来解决这个问题

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

这将是一个简单的写作解决方案 - 但我认为这是一个更抽象的解决方案 并使用累加器True将[Bool]和&amp; s作为此列表的第一个元素 这个结果将成为foldl的下一个累加器。

你的ε/ 2