Haskellで数独 の解説PDF

Haskellで書いた数独の自動解答プログラムの、解説PDFを作ってみました。こちら
以下のコードを解説しています。

import System
import List
import Array
import Char
import Monad

isSingle [x] = True
isSingle _ = False

slice n [] = []
slice n l = a:(slice n b) where (a,b) = splitAt n l

arrayList ar = [ar!idx | idx <- allCells]

allCells = range ((0,0),(8,8))
rowCells idx =
    let (row,col) = idx
    in range ((row,0),(row,8))
colCells idx =
    let (row,col) = idx
    in range ((0,col),(8,col))
boxCells idx =
    let (row,col) = idx
        a = (row `div` 3) * 3
        b = (col `div` 3) * 3
    in range ((a,b),(a+2,b+2))

unfixedCells ar = filter (\idx -> not (isSingle (ar!idx))) allCells

getCandidates ar idx =
    let used = concat [ar!x | x <- rowCells idx ++ colCells idx ++ boxCells idx, isSingle (ar!x)]
    in
    [1..9] \\ used

logicalSolve ar = 
    let ar' = foldl f ar $ unfixedCells ar
            where f ar idx = ar//[(idx, getCandidates ar idx)]
    in
      if any (\idx -> ar!idx /= ar'!idx) $ allCells
      then logicalSolve ar'
      else ar'

trialsList ar = [ar//[(idx,[x])] | x <- ar!idx] where idx = head $ unfixedCells ar

solve ar =
    let s ar | all (\idx -> isSingle (ar!idx)) $ allCells = return ar
             | any (\idx -> (ar!idx) == []) $ allCells = fail "fail"
             | otherwise = do t <- trialsList ar
                              solve t
    in 
      s (logicalSolve ar)

main :: IO ()
main = do
  let contents = [0,0,6,0,0,0,0,0,1,
                  0,7,0,0,6,0,0,5,0,
                  8,0,0,1,0,3,2,0,0,
                  0,0,5,0,4,0,8,0,0,
                  0,4,0,7,0,2,0,9,0,
                  0,0,8,0,1,0,7,0,0,
                  0,0,1,2,0,5,0,0,3,
                  0,6,0,0,7,0,0,8,0,
                  2,0,0,0,0,0,4,0,0]
  let start = listArray ((0,0),(8,8))
              $ map (\x -> if x == 0 then [1..9] else [x]) contents
  printArray (head (solve start))
      where printArray ar = mapM_ putStrLn $ (slice 9 l)
                where l = map intToDigit (concat (arrayList ar))

もともとには、ファイルから問題を読み込む処理もちゃんと書いてあったんですが、見やすくするためにそれは省きました。
8だの9だのマジックナンバーを定数にしていないのも、わざとです。
実は Gauche でも書いたので、それもいずれ文書に含めて、数独関数型言語入門といった感じにまとめて、HTMLに書き直そうと思っています。