如何使用replicateM?

时间:2013-09-24 17:48:48

标签: haskell

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

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

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

2 个答案:

答案 0 :(得分:2)

replicateM在这里是错误的选择:

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

这意味着在表达式replicateM 8 addqueen中,m a ~ ([Int] -> [[Int]])m ~ ((->) [Int])a ~ [[Int]]。它的类型是m [a] ~ ([Int] -> [[[Int]]])。这不是你想要的。

(如果您收到类型错误“没有(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]]

更新: 此表达式x1 = foldl1 (>=>) $ replicate 8 addqueen独立于Prolog术语,对应于a "goal"添加8个皇后的初始值解。它使用一个稍微以上基本级运算符“fish” 1 ,即left-to-right Kleisli composition operator >=>,定义为

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

即。 >=>是monadic函数的复合运算符。我们通过将最初为空的解决方案提供给x1来使用[ [] ] >>= x1

给您in the comments by Sassa NFx2 = foldl (>>=) [[]] $ replicate 8 addqueen的表达式仅使用基本monadic bind operator >>=,但仅作为一个整体使用。

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

答案 1 :(得分: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]]]