从Prolog和Haskell中思考 - 生成真值组合列表

Sho*_*hon 6 combinations haskell list-comprehension prolog translate

我知道一些Prolog,刚开始在Haskell做一些自学.我一直在努力解决Haskell99个问题,一路上学习并真正享受Haskell.有时我试图通过在Prolog中编写代码来解释我对问题空间的理解,然后思考该解决方案如何与Haskell中的函数方法相关.今晚,在处理逻辑问题(问题47和48)时,我分心试图完成构建一个包含n值的所有真值组合列表的简单任务.我想要一个功能tValues :: Int -> [[Bool]].这个问题可以在Prolog中以非常简单和声明的方式解决,例如:

combinations_of_n_truth_values(N, AllValues) :-
    findall(Values, n_truth_values(N, Values), AllValues).

n_truth_values(N, TruthValues) :-
    length(TruthValues, N),
    maplist(truth_value, TruthValues).

truth_value(true).
truth_value(false).
Run Code Online (Sandbox Code Playgroud)

使用时,变量AllValues将与所需的真值列表列表统一.我想知道一位经验丰富的Haskell程序员将如何解决同样的问题.我希望有一个同样简单明了的解决方案,但我似乎无法让我的Haskell大脑以正确的方式运作.

我使用列表推导摆弄了一些半类似物,如下所示:

tValues:: Int -> [[Bool]]
tValues 0 = []
tValues n = [v:vs | v  <- tValue
                  , vs <- tValues (n-1) ] 

tValue :: [Bool]
tValue = [True, False]
Run Code Online (Sandbox Code Playgroud)

tValues只返回[].我想我只需要一些人与人之间的互动来帮助我清醒一下,并且可以让我更深入地了解我.

非常感谢.

Zet*_*eta 9

在伪代码中,您的列表理解

[v:vs | v  <- tValue
      , vs <- tValues (n-1) ] 
Run Code Online (Sandbox Code Playgroud)

等于

for any combination of two elements in `tValue`  and `tValues (n-1)`
    cons the first onto the latter
Run Code Online (Sandbox Code Playgroud)

但是,tValues没有元素可以开始,它是一个空列表.让我们模拟这个n = 1:

tValues 1 = [v:vs | v  <- tValue
                  , vs <- tValues 0 ] 
          = [v:vs | v  <- [True, False]
                  , vs <- [] ] 
            -- since there is no vs
          = []
Run Code Online (Sandbox Code Playgroud)

这会在整个递归过程中传播.解决方案非常简单:更改基本案例以包含空组合:

tValues 0 = [[]] -- or: return []
Run Code Online (Sandbox Code Playgroud)

现在模拟产生:

tValues 1 = [v:vs | v  <- tValue
                  , vs <- tValues 0 ] 
          = [v:vs | v  <- [True, False]
                  , vs <- [[]]] 
            -- vs is []
          = [True:[],False:[]]
          = [[True],[False]]
Run Code Online (Sandbox Code Playgroud)

这正是我们想要的.


Wil*_*ess 6

随着列表monad,

g n = mapM (\_-> [True, False]) [1..n]
Run Code Online (Sandbox Code Playgroud)

关于你的功能的基本情况.当函数返回一个包含所有真值列表长度的列表时n,它n=0会返回一个列表,其中包含长度为0的所有真值列表,即包含一个空列表的列表.

  • 深入研究monadic库函数,你的`序列.复制n`已经存在为`Control.Monad.replicateM n`. (4认同)
  • 所以`replicateM n [True,False]`肯定会赢得短暂的比赛! (4认同)
  • 为了明确"使用monad"这一部分,我们可以把它写成`序列.复制n $ [True,False]` (3认同)
  • @ m09`mapM`中的`M`也显示了这一点.:) (2认同)
  • 实际上,这正是*your*Prolog代码,`maplist(truth_value,N_long_list)`的翻译,因为Haskell的列表monad通过收集谓词的所有解的列表来表达非确定性,就像通过隐式`findall`一样.所以这是完全相同的代码,地图的地图.:)欢迎你.:) (2认同)
  • "替代计算策略"正是通常如何看待monad:列表类型`[]`用于非确定性,"可能"用于失败的可能性,"可能"允许无法携带自己的信息等. (2认同)