你必须采取的关键步骤是思考归纳地。您当前的解决方案:
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)
因此,我们将列表的尾部评估为某个值(递归地),并使用&&
运算符组合thatvalue 与当前值,这就是我们编写的函数。
由列表的递归结构驱动的递归和归纳是the编程中学习的关键技术。如果你能写出这篇文章,你就向前迈出了一大步。