import Data.List (permutations, (\\))

latinSquare :: Eq a => [a] -> [a] -> [[a]]
latinSquare [] [] = []
latinSquare c r
  | head r /= head c = []
  | otherwise = reverse <$> foldl addRow firstRow perms
  where
    
    perms =
      tail $
        fmap
          (fmap . (:) <*> (permutations . (r \\) . return))
          c
    firstRow = pure <$> r
    addRow tbl rows =
      head
        [ zipWith (:) row tbl
          | row <- rows,
            and $ different (tail row) (tail tbl)
        ]
    different = zipWith $ (not .) . elem

printTable :: Show a => [[a]] -> IO ()
printTable tbl =
  putStrLn $
    unlines $
      unwords . map show <$> tbl