给定 SML 中的变量列表,生成所有真值分配的列表?

Generating a list of all truth assignments given a list of variables in SML?

我正在尝试用 SML 编写一个给定变量列表的函数,它 returns 每个可能的布尔赋值的元组列表。

基本上,我希望代码执行此操作:

fun allAssignments ["p", "q"] = 
  [[("p", True),  ("q", True) ]
   [("p", True),  ("q", False)]
   [("p", False), ("q", True) ]
   [("p", False), ("q", False)]]

然而,我写了这个函数,虽然它对我来说很有意义,但我一直收到 tycon 不匹配错误,我无法纠正它:

fun allAssignments nil = [[]]
  | allAssignments (x::xs) = [(x, true)::allAssignments xs] @ [(x, false)::allAssignments xs]

谁能帮我指明正确的方向?谢谢!

根据您的示例,allAssignments 需要具有类型 string list -> (string * bool) list list(或者可能是 'a list -> ('a * bool) list list''a list -> (''a * bool) list list,但我会坚持使用 string 为简单起见;两种方式的实现都是相同的)。

因此,allAssignments xs 必须具有类型 (string * bool) list list,并且 (x, true) 必须具有类型 string * bool。但是 (x, true) :: allAssignments xs 是类型不匹配,因为 :: 期望它的第二个参数是一个列表,其元素与第一个参数具有相同的类型,而在您的情况下,第二个参数是一个列表,其元素是lists(第一个参数不是)。

如果我们想象一个不实际检查类型的标准 ML 版本,您的 allAssignments 版本将给出以下结果:

  • allAssignments [][[]]
  • allAssignments ["q"][[("q", true), []], [("q", false), []]]
  • allAssignments ["p", "q"][[("p", true), [("q", true), []], [("q", false), []]], [("p", false), [("q", true), []], [("q", false), []]]]

如您所见,它并没有真正解决问题。一个问题是 "q" 的赋值比 "p" 的赋值嵌套在更多层的列表中(因此出现类型错误)。另一个问题是 ("p", true)("p", false) 每个只出现一次,而 ("q", true)("q", false) 每个出现两次。

要解决此问题,您需要实际“打开”allAssignments xs 并将 (x, true) 添加到它包含的每个单独列表中,然后 (x, false) 也是如此。

这是一种方法,使用 map:

fun allAssignments nil = [nil]
 |  allAssignments (x::xs) =
      (map (fn assignments => (x, true) :: assignments) (allAssignments xs))
      @ (map (fn assignments => (x, false) :: assignments) (allAssignments xs))

虽然我应该提到这个实现根本不是最优的;计算时间和内存使用量都可以显着减少,特别是如果您不关心返回分配的顺序。