7

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

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

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

4

2 回答 2

3

replicateM这里是错误的选择:

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

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

这意味着表达式replicateM 8 addqueen中,类型的addqueen匹配与m a,给予m a ~ ([Int] -> [[Int]]),即m ~ ((->) [Int])a ~ [[Int]]。因此 的类型replicateM 8 addqueenm [a] ~ ([Int] -> [[[Int]]])。这不是你想要的。

(如果您收到类型错误“No instance for (Monad ((->) [Int])),请先尝试加载例如Control.Applicative,以引入 的定义instance Monad ((->) 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 (>=>) $ replicate 8 addqueen本身具有含义。在 Prolog 术语中,它是在初始解决方案中添加 8 个皇后“目标” 。我们通过 g给它一个最初为空的解决方案来使用,[ [] ] >>= g.

(这使用了一个略高于基本级别的运算符“fish” 1 ,即从左到右的 Kleisli 组合运算符>=>,定义为

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

ie>=>是一元函数的组合运算符。)

Sassa NF 在评论中给您的表达式,foldl (>>=) [[]] $ replicate 8 addqueen使用基本的一元绑定运算符>>=,但只能作为一个整体工作。

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

于 2013-09-24T19:39:00.927 回答
0

你错过了空间

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 >>=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]]]
于 2013-09-24T17:56:48.727 回答