haskell – 如何使用replicateM?

我刚开始学习编写
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

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

最佳答案 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])和〜[[Int]].它的类型是m [a]〜([Int] – > [[[Int]]]).这不是你想要的.

(如果你得到一个类型错误“没有实例(Monad(( – >)[Int]))”,请先尝试加载例如Control.Applicative,以引入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术语,对应于向初始解决方案添加8个皇后的a “goal”.它使用略高于基本水平的运算符“鱼”1,即left-to-right Kleisli composition operator >=>,定义如此

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

即> =>是一元函数的复合运算符.我们通过将最初为空的溶液输入其中来使用x1,[[]]>> = x1.

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

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

点赞