Here's another example, I think, with the admonition that I'm a programmer, not a mathematician. Even so, I was just now researching various operations in relationship to group-like structures, and came about the following example.

# Mixing colours

It relates to mixing colours using *Red Green Blue* (RGB) colours. These are, for example, used in HTML pages.

As in my other example here on the page, I'm going to give my example in Haskell, but I'll try to provide enough information that non-programmers should be able to get the gist of it.

We can define the entire domain (set of possible values) as a data type called `RGBColor`

:

```
data RGBColor = RGBColor { red :: Byte, green :: Byte, blue :: Byte }
```

This simply states that an `RGBColor`

value has three constituent `Byte`

(8-bit) values for the colours red, green, and blue. The lower the number, the darker the colour, and vice versa. Here's a single example that renders a yellow colour:

```
RGBColor 255 255 0
```

If you have two colours, you can mix them by taking half of the `red`

component from each, half of the `green`

component from each, and so on.

If we have, e.g.

```
λ> let x = RGBColor 100 0 128
λ> let y = RGBColor 200 255 64
```

we can mix these two `RGBColor`

values (`x`

and `y`

) with a `mix`

function:

```
λ> x `mix` y
RGBColor {red = 150, green = 128, blue = 96}
```

This returns a new `RGBColor`

value with a mix of the two input colours. The `mix`

function is a **binary operation** that takes two `RGBColor`

values and returns an `RGBColor`

value. Therefore, if I've understood just a minimum of all this, it must be at least a **magma**. Is it anything else? I don't think it is.

## Associativity

Is the `mix`

operation associative? No, it isn't, because it's easy to come up with a counter-example:

```
λ> (RGBColor 67 108 13 `mix` RGBColor 33 114 130) `mix` RGBColor 38 104 245
RGBColor {red = 44, green = 108, blue = 158}
λ> RGBColor 67 108 13 `mix` (RGBColor 33 114 130 `mix` RGBColor 38 104 245)
RGBColor {red = 52, green = 108, blue = 100}
```

Depending on where you put the brackets, the result is different, where it should have been the same.

## Identity

Does an identity element exist for the `mix`

operation? Here, we can use a combination of brute force and a counter-example to show that no identity element exists.

Let's arbitrarily pick a near-black colour to start with:

```
λ> let nearBlack = RGBColor 1 1 1
```

The reason I didn't pick absolute black (`RGBColor 0 0 0`

) is that, due to rounding when mixing, there are eight candidates for absolute black. As we shall see, there's only one candidate for `nearBlack`

:

```
λ> filter (\e -> e `mix` nearBlack == nearBlack) allColors
[RGBColor {red = 1, green = 1, blue = 1}]
```

This expression searches through `allColors`

for a value, `e`

, that behaves like the left identity for `nearBlack`

. Here, `allColors`

is an enumeration of *all*
16,777,216 possible `RGBColor`

values - yes: it takes a couple of minutes to run the above search, but nothing more than that...

The point here is that *if* there's a left identity for `mix`

, it *must* be `RGBColor 1 1 1`

, because that's the only possible candidate for `nearBlack`

. It holds for `nearBlack`

:

```
λ> RGBColor 1 1 1 `mix` nearBlack
RGBColor {red = 1, green = 1, blue = 1}
λ> nearBlack == it
True
```

The return value (implicitly called `it`

) is, indeed, equal to `nearBlack`

. Can we find a counter-example where the candidate color does *not* behaves like the left identity?

Yes, easily:

```
λ> RGBColor 1 1 1 `mix` RGBColor 3 3 3
RGBColor {red = 2, green = 2, blue = 2}
λ> RGBColor 3 3 3 == it
False
```

The candidate `RGBColor 1 1 1`

does *not* behave as the left identity for the colour `RGBColor 3 3 3`

, but it was the only candidate we had. Therefore, there's no identity element for the `mix`

operation.

## Invertibility

Is the `mix`

operation invertible? No. We can demonstrate that with another combination of a counter-example and brute force. Pick these two values:

```
λ> let a = RGBColor 94 35 172
λ> let b = RGBColor 151 185 7
```

These will serve as the `a`

and `b`

in the definition of invertibility. Here, I'm using the definition from Wikipedia's article on quasigroups, because that's the only remaining type of operation that `mix`

can be, now that I have demonstrated that it's neither associative nor has identity.

For every `a`

and `b`

, there must exist an `x`

and `y`

such that:

```
a `mix` x = b,
y `mix` a = b
```

First, try to find `x`

for the above `a`

and `b`

:

```
λ> any (\x -> a `mix` x == b) allColors
False
```

The built-in `any`

function returns `True`

if there's *any* value in `allColors`

that satisfy the lambda expression in the middle. The answer is `False`

, so there's no need to continue. The above `a`

and `b`

serve as a counter-example, because there's no `x`

that satisfy left division.

# Summary

Mixing of RGB colours seems to be a magma, but no other type of operation. It doesn't have associativity, an identity element, and nor is it invertible.

# Appendix

For programmers, here's the full code listing:

```
module RGB where
import Data.Bits ((.&.))
import Data.Word (Word8)
import Text.Printf (printf, PrintfType)
type Byte = Word8
data RGBColor = RGBColor { red :: Byte, green :: Byte, blue :: Byte }
deriving (Eq, Show, Bounded)
instance Enum RGBColor where
toEnum i = RGBColor r g b
where
r = toEnum $ (i .&. 0xFF0000) `div` 0x10000
g = toEnum $ (i .&. 0xFF00) `div` 0x100
b = toEnum $ i .&. 0xFF
fromEnum x =
fromEnum (red x) * 256 * 256 + fromEnum (green x) * 256 + fromEnum (blue x)
mix :: RGBColor -> RGBColor -> RGBColor
mix x y = RGBColor newRed newGreen newBlue
where
newRed = round $ (toRational ( red x) + toRational ( red y)) / 2
newGreen = round $ (toRational (green x) + toRational (green y)) / 2
newBlue = round $ (toRational ( blue x) + toRational ( blue y)) / 2
toWebColor :: PrintfType t => RGBColor -> t
toWebColor (RGBColor r g b) = printf "#%02X%02X%02X" r g b
allColors :: [RGBColor]
allColors = [minBound .. maxBound]
```