content: -- The classic 8-queens problem made famous by Wirth.
  -- This version Colin Runciman, March 2000.
  
  main =
      if null solutions then putStrLn "no solution!"
      else putStr (board (head solutions))
      where
      solutions = queens 8
  
  queens :: Int -> [[Int]]
  queens n = valid n n
  
  valid :: Int -> Int -> [[Int]]
  valid 0 n = [[]]
  valid m n = filter safe (extend n (valid (m-1) n))
  
  extend n b = cp (fromTo 1 n) b
  
  cp :: [a] -> [[a]] -> [[a]]
  cp [] y = []
  cp (a:x) y = map (a:) y ++ cp x y
  
  safe (a:b) = no_threat a b 1
  
  no_threat a [] m = True
  no_threat a (b:y) m =
      a /= b && a+m /= b && a-m /= b && no_threat a y (m+1)
  
  board :: [Int] -> String
  board b =
      unlines (concat (zipWith rank (from 1) b))
    where
      rank r qcol =
          map line ["o o o", " \\|/ ", " === "]
        where
          line crown_slice =
              concat (zipWith square (from 1) b)
            where
              square scol _ =
                  if scol == qcol then crown_slice
                  else if (scol `rem` (2::Int)) == (r `rem` (2::Int)) then "....."
                  else "     "
  
  -- in place of ..
  
  from :: Int -> [Int]
  from n = n : from (n+1)
  
  fromTo :: Int -> Int -> [Int]
  fromTo m n = if m > n then [] else m : fromTo (m+1) n
  