# The Universe of Discourse

Thu, 08 Nov 2018

I want to build an adjacency matrix for the vertices of a cube; this is a matrix that has m[a][b] = 1 exactly when vertices a and b share an edge. We can enumerate the vertices arbitrarily but a convenient way to do it is to assign them the numbers 0 through 7 and then say that vertices !!a!! and !!b!! are adjacent if, regarded as binary numerals, they differ in exactly one bit, so:

   import Data.Bits
a adj b = if (elem (xor a b) [1, 2, 4]) then 1 else 0


This compiles and GHC infers the type

   adj :: (Bits a, Num a, Num t) => a -> a -> t


Fine. Now I want to build the adjacency matrix, which is completely straightforward:

    cube = [ [a adj b | b <- [0 .. 7] ] | a <- [0 .. 7] ]  where
a adj b = if (elem (xor a b) [1, 2, 4]) then 1 else 0


Ha ha, no it isn't; in Haskell nothing is straightforward. This produces 106 lines of type whining, followed by a failed compilation. Apparently this is because because 0 and 7 are overloaded, and could mean some weird values in some freakish instance of Num, and then 0 .. 7 might generate an infinite list of 1-graded torsion rings or something.

To fix this I have to say explicitly what I mean by 0. “Oh, yeah, by the way, that there zero is intended to denote the integer zero, and not the 1-graded torsion ring with no elements.”

        cube = [ [a adj b | b <- [0 :: Integer .. 7] ] | a <- [0 .. 7] ]  where
a adj b = if (elem (xor a b) [1, 2, 4]) then 1 else 0


Here's another way I could accomplish this:

        zero_i_really_mean_it = 0 :: Integer
cube = [ [a adj b | b <- [zero_i_really_mean_it .. 7] ] | a <- [0 .. 7] ] where
a adj b = if (elem (xor a b) [1, 2, 4]) then 1 else 0


        cube = [ [a adj b | b <- numbers_dammit [0 .. 7] ] | a <- [0 .. 7] ] where
p adj q = if (elem (xor p q) [1, 2, 4]) then 1 else 0