对于作业我必须生成如下的真值表:
combinations :: Int -> [[Bool]]
组合3应输出:
[[False, False, False],[False, False, True],[False, True, False],[False, True, True][True, False, False][True, False, True],[True, True, False],[True, True, True]]
我可以做一个列表理解:
combinations n = [[a,b] | a<-[True, False], b <-[True, False]]
但这并不适用于任意数字。
你可以给我一个暗示吗?答案 0 :(得分:2)
你应该递归推理。
要生成n
- 组合,您可以按以下步骤操作。首先,生成所有n-1
- 组合:将此列表命名为c
(这是布尔列表的列表)。然后,对于xs
的每个元素c
(此处xs
是布尔值列表),生成x:xs
,其中x
是任意布尔值。专门处理案例n=0
,以提供基本案例。
答案 1 :(得分:1)
添加@chi的回答,这是实现该功能的递归方式。我已将其重命名为快捷方式truths
:
truths :: Int -> [[Bool]]
truths 0 = [[]]
truths n = do
b <- [True,False]
map (b :) (truths (n - 1))
最后3行可以改写为
truths n = [True,False] >>= \b -> map (b :) (truths (n - 1))
这里我们只是为前一个结果中的每个元素添加一个true / false值。唯一的边缘情况是负数,但你可以自己解决这个问题。
我在GHCi中尝试了这个解决方案,它在大约0.6秒内计算truths 10
,这是令人印象深刻的,考虑到有1024个列表,每个列表包含10个元素。
我还使用sequence
中的Control.Monad
提出了另一个更有趣的版本:
import Control.Monad (sequence)
truths :: Int -> [[Bool]]
truths n = sequence (replicate n [True,False])
这将产生相同的输出。请注意,它也可以用无点样式重写,效果相同:
truths = sequence . flip replicate [True,False]