【问题标题】:How to use replicateM solving the eight queens problem?如何使用replicateM解决八皇后问题?
【发布时间】:2013-09-24 17:48:47
【问题描述】:

我刚开始学习编写 Haskell 代码,如果这是一个愚蠢的问题,我深表歉意。我试图通过使用[] monad 来重做八皇后问题。这是代码,

import Control.Monad

addqueen :: [Int] -> [[Int]]
addqueen xs = [ x:xs | x <- [1,2..8], 
    not $ x `elem` xs 
        || (any (\ (index,q) -> abs (x-q) == index) $ zip [1..] xs) ]

当我尝试时

[[]] >>= replicateM 8 addqueen

它不起作用,但会产生以下错误:

Couldn't match expected type `t0 -> t1' with actual type `[[a0]]'
The first argument of ($) takes one argument,
but its type `[[a0]]' has none
In the expression: [[]] >>= replicateM 8 $ addqueen
In an equation for `it': it = [[]] >>= replicateM 8 $ addqueen

那么我如何在这里实现我想要做的呢?

【问题讨论】:

  • 目前还不清楚您希望[[]]&gt;&gt;= replicateM 8 addqueen 做什么。请注意,[[]] &gt;&gt;= f 等于 f []
  • 我可以得到结果,如果我这样做 "[[]]>>=addqueen >>=addqueen >>=addqueen >>=addqueen >>=addqueen >>=addqueen >>=addqueen > >=addqueen" 但这真的很乏味。我正在寻找一种“语法糖”来简化调用。
  • 如果我没记错的话,看起来像 iterate (&gt;&gt;= addqueen) [[]] !! 8
  • 啊,这就像一个魅力!谢谢哥们!
  • foldl (&gt;&gt;=) [[]] $ replicate 8 addqueen

标签: haskell monads type-mismatch n-queens replicate


【解决方案1】:

replicateM 在这里是错误的选择:

Prelude Control.Monad> :t replicateM
replicateM :: (Monad m) => Int -> m a -> m [a]

Prelude Control.Monad> :t addqueen
addqueen :: [Int] -> [[Int]]

这意味着表达式replicateM 8 addqueenaddqueen的类型与m a匹配,得到m a ~ ([Int] -&gt; [[Int]]),即m ~ ((-&gt;) [Int])a ~ [[Int]]。因此replicateM 8 addqueen 的类型是m [a] ~ ([Int] -&gt; [[[Int]]])。这不是你想要的。

(如果您收到类型错误“没有(Monad ((-&gt;) [Int])) 的实例”,请先尝试加载例如Control.Applicative,以引入instance Monad ((-&gt;) r) 的定义。如果您'重新使用旧版本的 GHC)。

试试这个吧:

Prelude> :m +Control.Monad

Prelude Control.Monad> :t (>=>)
(>=>) :: (Monad m) => (a -> m b) -> (b -> m c) -> a -> m c

Prelude Control.Monad> :t foldl1 (>=>) $ replicate 8 addqueen
foldl1 (>=>) $ replicate 8 addqueen :: [Int] -> [[Int]]

Prelude Control.Monad> :t [[]] >>= ( foldl1 (>=>) $ replicate 8 addqueen )
[[]] >>= ( foldl1 (>=>) $ replicate 8 addqueen ) :: [[Int]]

更新: 表达式 g = foldl1 (&gt;=&gt;) $ replicate 8 addqueen 有其自身的含义。在 Prolog 术语中,它是 a "goal" 在初始解决方案中添加 8 个皇后。我们使用 g,给它一个最初为空的解决方案[ [] ] &gt;&gt;= g

( 这使用了一个稍微高于基本级别的运算符“fish”1,即left-to-right Kleisli composition operator &gt;=&gt;,这样定义

(m >>= a) >>= b  ===  m >>= (a >=> b)

&gt;=&gt; 是一元函数的组合运算符。 )

给你的表达式in the comments by Sassa NFfoldl (&gt;&gt;=) [[]] $ replicate 8 addqueen,使用基本的monadic bind operator &gt;&gt;=,但只能作为一个整体起作用。

1http://haskellrescue.blogspot.com/2011/03/cooking-delicious-fish.html

【讨论】:

    【解决方案2】:

    你错过了空格

    addqueen xs = [x:xs|x<-[1,2..8], not $ x `elem` xs 
        || (any (\(index,q) -> abs (x-q) ==index) $ zip [1..] xs)]
    

    第二,不要同时使用多个中缀函数

    --this code is invalid:
    [[]] >>= replicateM 8 $ addqueen -- read as [[]] >>= (replicateM 8 $) addqueen
    

    原因是:infixl 1 &gt;&gt;=infixr 0 $

    第三,如果您使用 GHCi,请为“空”数据编写签名。

    >([[]] :: [[Int]])>>= replicateM 8 addqueen
    

    您的代码有效

    > [[]]>>= replicateM 8 addqueen
    [[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]],[[1],[2],[3],[4],[5],[6],[7],[8]]]
    

    【讨论】:

    • 我仍然无法让它工作。这是我得到的:没有使用 replicateM' Possible fix: add an instance declaration for (Monad ((-&gt;) [Int])) In the second argument of (>>=)' 产生 (Monad ((->) [Int])) 的实例,即replicateM 8 addqueen' In the expression: ([[]] :: [[Int]]) &gt;&gt;= replicateM 8 addqueen In an equation for it':it = ([[]] :: [[Int]]) >>= replicateM 8 addqueen
    • replicateM 3 (1+) $ 4 ==> [5,5,5]。不是[5,6,7]
    • @user2812201 现在你缺少instance Monad ((-&gt;) r)。但这是一件好事。试试Prelude&gt; :m +Control.Applicative;代码可以工作,但它不会做你想做的事,而是做别的事情。
    • [[]] &gt;&gt;= replicateM 8 $ addqueen 实际上读作([[]] &gt;&gt;= replicateM 8) $ addqueen 这当然没有多大意义。
    猜你喜欢
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 2012-10-24
    相关资源
    最近更新 更多