## Bitwise-oriented semigroup and monoid newtype wrappers for Data.Bits.Bits instances

I've found myself needing these often, and given the existence of similar newtypes for directing `(<>)`

and `mempty`

for a range of other types, these are conspicuous by their absence. Additionally, while `oneBits`

isn't technically necessary, it's a lot more concise than `complement zeroBits`

, and I found myself needing it often.

To that end, I've sketched up this implementation. Technically speaking, GND isn't needed, but it means I don't have to repeat myself a lot. These could be made even more concise with `coerce`

, but I decided not to do that, since that would require `TypeApplications`

. I've limited derivation to methods that are specifically about bitwise operations, rather than stuff like `Num`

.

```
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Bits.Extra where
import Data.Bits ( Bits(..)
, FiniteBits(..)
)
-- | Monoid under bitwise AND.
newtype Conj a = Conj { getConj :: a }
deriving (Eq, Bounded, Enum, Bits, FiniteBits)
instance (Bits a) => Semigroup (Conj a) where
(Conj x) <> (Conj y) = Conj (x .&. y)
instance (Bits a) => Monoid (Conj a) where
mempty = Conj . complement $ zeroBits
-- | Monoid under bitwise OR.
newtype Disj a = Disj { getDisj :: a }
deriving (Eq, Bounded, Enum, Bits, FiniteBits)
instance (Bits a) => Semigroup (Disj a) where
(Disj x) <> (Disj y) = Disj (x .|. y)
instance (Bits a) => Monoid (Disj a) where
mempty = Disj zeroBits
-- | Semigroup under bitwise XOR.
newtype Xor a = Xor { getXor :: a }
deriving (Eq, Bounded, Enum, Bits, FiniteBits)
instance (Bits a) => Semigroup (Xor a) where
(Xor x) <> (Xor y) = Xor (x `xor` y)
-- | Semigroup under bitwise \'equality\'; defined as '1' if the corresponding
-- bits match, '0' otherwise.
newtype Iff a = Iff { getIff :: a }
deriving (Eq, Bounded, Enum, Bits, FiniteBits)
instance (Bits a) => Semigroup (Iff a) where
(Iff x) <> (Iff y) = Iff . complement $ (x `xor` y)
-- not strictly necessary, but would be a big help
-- probably should be INLINE
oneBits :: (Bits a) => a
oneBits = complement zeroBits
```

Potentially this could include more, such as instances of `Ord`

based on lexicographic ordering on the bits, rather than defaulting to the underlying one (such as the one for `Int`

, which I believe is numeric). However, that's a separate issue. I also don't know if these belong in `Data.Bits`

or `Data.Semigroup`

(or `Data.Monoid`

I guess).

## Trac metadata

Trac field | Value |
---|---|

Version | 8.6.2 |

Type | FeatureRequest |

TypeOfFailure | OtherFailure |

Priority | normal |

Resolution | Unresolved |

Component | libraries/base |

Test case | |

Differential revisions | |

BlockedBy | |

Related | |

Blocking | |

CC | |

Operating system | |

Architecture |