使用布尔值列出 Haskell 中的组合

List combinations in Haskell with booleans

所以,我最近开始学习 Haskell,我遇到了一个问题,我需要计算所有可能的结果 (2^n) 如果翻转 n 个硬币。例如,如果掷 2 个硬币,输出应该是 [[H, H], [H, T], [T, H], [T, T]]。同样,对于 3 个硬币,它应该是 [[H, H, H], [H, H, T], [H, T, H], [T, H, H], [H, T, T], [ T, T, H], [T, H, T], [T, T, T]]。我的函数不适用于 n 的任意值。它只有在我以前知道 n 的情况下才有效。我正在考虑使用递归,但我不确定语法。

这是我的代码:

outcomes(x:xs) = [[a, b] | a <- states x, b <- states (head xs)]

其中,函数状态为:

states _ = [True, False]

此函数适用于 n = 2。请告诉我如何使其适用于任何输入 n。

由于您希望您的函数适用于任意次数的翻转 n,它可能应该接受一个 Int 参数:否则您将如何获得一个 Int?而且,正如评论中所建议的那样,递归是在 Haskell 中执行类似循环的事情的方法,您将需要一个基本案例和一个递归案例。对于计数,0 是一个自然的基本情况,也是这里使用的最佳情况,但是使用 1 作为基本情况对于初学者来说更容易理解一些,所以我们让函数 break for n=0 现在。

因此,您需要一个具有两种模式的函数:

outcomes :: Int -> [[Bool]]
outcomes 1 = _
outcomes n = _

1 的结果应该是什么,即翻转一次?一旦你有了它,你能根据 outcomes (n - 1) 实现 outcomes n 吗?如果是这样,你就完成了。如果没有,您最好 material 提出一个新问题,因为您已经完成了解决方案的一半。

额外加分,一旦完成,看看你是否能充分理解递归,为 outcomes 0 选择一个可以替代 outcomes 1 作为你的基本情况的好值。

你可以在这里使用递归。我们可以构造一个函数,它接受一个元素列表 [a] 和一个 Int,所以:

outcomes :: [a] -> Int -> [[a]]

如果整数小于或等于零,则只有一个可能的结果是空列表。所以我们 return 一个包含一个空列表的列表:

outcomes _ n | n <= 0 = [[]]

至于递归的情况,我们可以从列表中取出一个元素,然后使用相同的值列表进行递归,但是我们创建的结果少了一个元素,然后我们将我们取出的元素添加到这些结果中。

outcomes ls n = [ … | x < ls, xs <- … ]

这里我将 部分留作练习。在第一个 片段中,您需要在 xs 前面加上 x。在第二个中,您需要进行递归调用。

因此,将其放在一起,我们将 outcomes 实现为:

outcomes :: [a] -> Int -> [[a]]
outcomes _ n | n <= 0 = [[]]
outcomes ls n = [ … | x < ls, xs <- … ]