我有以下问题:
定义功能
and, or :: [Bool] -> Bool
给出了布尔列表的连接和分离。例如,
and [False, True] = False or [False, True] = True
在空列表
and
上提供True
,or
提供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
答案 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) = ...
好的,对于空列表and
是True
。如果列表以“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