```module Logic.Board;

import Stdlib.Prelude open;
import Stdlib.Debug.Fail open;
import Logic.Square open public;
import Logic.Symbol open public;
import Logic.Extra open;

--- A 3x3 grid of ;Square;s
type Board := board : List (List Square) → Board;

--- Returns the list of numbers corresponding to the empty ;Square;s
possibleMoves : List Square → List Nat
| nil := nil
| (empty n :: xs) := n :: possibleMoves xs
| (_ :: xs) := possibleMoves xs;

--- ;true; if all the ;Square;s in the list are equal
full : List Square → Bool
| (a :: b :: c :: nil) := ==Square a b && ==Square b c
| _ := failwith "full";

diagonals : List (List Square) → List (List Square)
| ((a1 :: _ :: b1 :: nil)
:: (_ :: c :: _ :: nil)
:: (b2 :: _ :: a2 :: nil)
:: nil) := (a1 :: c :: a2 :: nil) :: (b1 :: c :: b2 :: nil) :: nil
| _ := failwith "diagonals";

columns : List (List Square) → List (List Square) := transpose;

rows : List (List Square) → List (List Square) := id;

--- Textual representation of a ;List Square;
showRow (xs : List Square) : String :=
concat (surround "|" (map showSquare xs));

showBoard : Board → String
| (board squares) := unlines (surround "+---+---+---+" (map showRow squares));
```