我正在试图理解
Select
单子的工作原理。显然,它是Cont
的近亲,可用于回溯搜索。
我有一个基于列表的解决n皇后问题的方案:-- All the ways of extracting an element from a list.
oneOf :: [Int] -> [(Int,[Int])]
oneOf [] = []
oneOf (x:xs) = (x,xs) : map (\(y,ys) -> (y,x:ys)) (oneOf xs)
-- Adding a new queen at col x, is it threathened diagonally by any of the
-- existing queens?
safeDiag :: Int -> [Int] -> Bool
safeDiag x xs = all (\(y,i) -> abs (x-y) /= i) (zip xs [1..])
nqueens :: Int -> [[Int]]
nqueens queenCount = go [] [1..queenCount]
where
-- cps = columsn of already positioned queens.
-- fps = columns that are still available
go :: [Int] -> [Int] -> [[Int]]
go cps [] = [cps]
go cps fps = [ps | (p,nfps) <- oneOf fps, ps <- go (p:cps) nfps, safeDiag p cps]
我在努力调整这个解决方案以使用Select
,但不太顺利。
看起来Select
可以让你抽象出用于比较答案的“评估函数”。该函数被传递给runSelect
。我有一种感觉,我的解决方案中的safeDiag
可能可以作为评估函数,但如何结构化Select
计算本身呢?
此外,仅使用Select
单子是否足够,还是需要在列表上使用转换器版本?
Select
单子类型吗?我的理解是,Select
尝试证明可能解决方案的存在(作为证明的见证)。Select
的典型示例是 SAT 求解器。你可能可以通过在列表单子类型上使用SelectT
强制执行某些操作,但我更确信你真正需要使用Select
单子类型。 - AlecSelect
在回溯搜索中很好用,而n皇后问题是这种类型的原型问题,所以我认为它是monad的一个很好的使用案例。 - danidiazSelect
单子,而是这个项目:queenslogic 使用Logic
单子通过回溯法解决 N 皇后问题。 - Dave Compton