我想了解Select
monad是如何工作的。顯然,它是Cont
的表親,它可以用於回溯搜索。如何使用Select monad來解決n皇后問題?
我有這個基於列表的解決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
monad就足夠了,還是我需要在列表上使用變換器版本?
您確定要「選擇」monad嗎?我對「選擇」的理解是它試圖證明存在一種可能的解決方案(作爲證明證明)。 「Select」的典型例子是SAT求解器。你可能會用'SelectT'強制通過列表monad,但我更確定你會真正使用select monad。 – Alec
@Alec我讀過「Select」適用於回溯搜索,而n-queens是這種類型的原型問題,所以我認爲這對monad來說是一個很好的用例。 – danidiaz
區別可能是回溯到找到所有解決方案和回溯,直到找到解決方案。然後,我再一次只玩過「選擇」,所以不要拿任何我認真說的話。 – Alec