module Queens where -- Appending two lists to form a list append [] ys = ys append (x:xs) ys = x : append xs ys -- "Bind" a list and a element-to-list function to form a list bind [] f = [] bind (x:xs) f = append (f x) (bind xs f) -- The list of solutions to the eight-queens problem eightQueens = bind (addAnyQueen []) (\queens -> bind (addAnyQueen queens) (\queens -> bind (addAnyQueen queens) (\queens -> bind (addAnyQueen queens) (\queens -> bind (addAnyQueen queens) (\queens -> bind (addAnyQueen queens) (\queens -> bind (addAnyQueen queens) addAnyQueen)))))) -- The list of ways (either empty or singleton) to add to a list of existing -- queens any new queen without conflict addAnyQueen queens = bind anyQueen (\q -> addGivenQueen queens q) -- The list of ways (either empty or singleton) to add to a list of existing -- queens a given new queen without conflict addGivenQueen [] new = [[new]] addGivenQueen (old:olds) new = if conflict old new then [] else bind (addGivenQueen olds new) (\queens -> [old:queens]) -- Whether two queens conflict with each other or come in the wrong order conflict (x1,y1) (x2,y2) = let dx = x2 - x1 dy = y2 - y1 in dx <= 0 || dy == 0 || dx == dy || dx == -dy -- The list of possible queen locations on a 8-by-8 board anyQueen = bind coordinate (\x -> bind coordinate (\y -> [(x,y)])) -- The list of possible coordinates on a 8-by-8 board coordinate = [1..8]