    {-# LANGUAGE DefaultSignatures, ScopedTypeVariables #-}

    -- From http://stackoverflow.com/a/15911213

    module Data.Text.ICU.BitMask
           (
        -- * Bit mask twiddling API
        -- $api
        -- * Types
          ToBitMask(..)
        -- * Functions
        , fromBitMask
        , highestValueInBitMask
        ) where

    import Data.Bits ((.&.), (.|.))
    import Data.Maybe (listToMaybe)

    -- $api
    -- Conversion to and from enumerated types representable as
    -- a compact bitmask.

    class ToBitMask a where
      toBitMask :: a -> Int

    instance (ToBitMask a) => ToBitMask [a] where
      toBitMask :: [a] -> Int
    toBitMask = (a -> Int -> Int) -> Int -> [a] -> Int
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    (.|.) (Int -> Int -> Int) -> (a -> Int) -> a -> Int -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Int
    forall a. ToBitMask a => a -> Int
    toBitMask) Int
    0

    fromBitMask :: (Enum a, Bounded a, ToBitMask a) => Int -> [a]
    fromBitMask :: forall a. (Enum a, Bounded a, ToBitMask a) => Int -> [a]
    fromBitMask Int
    bm = (a -> Bool) -> [a] -> [a]
    forall a. (a -> Bool) -> [a] -> [a]
    filter a -> Bool
    forall {a}. ToBitMask a => a -> Bool
    inBitMask ([a] -> [a]) -> [a] -> [a]
    forall a b. (a -> b) -> a -> b
    $ a -> [a]
    forall a. Enum a => a -> [a]
    enumFrom a
    forall a. Bounded a => a
    minBound
      where inBitMask :: a -> Bool
    inBitMask a
    val = (Int
    bm Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .&. a -> Int
    forall a. ToBitMask a => a -> Int
    toBitMask a
    val) Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == a -> Int
    forall a. ToBitMask a => a -> Int
    toBitMask a
    val

    highestValueInBitMask :: (Enum a, Bounded a, ToBitMask a) => Int -> Maybe a
    highestValueInBitMask :: forall a. (Enum a, Bounded a, ToBitMask a) => Int -> Maybe a
    highestValueInBitMask = [a] -> Maybe a
    forall a. [a] -> Maybe a
    listToMaybe ([a] -> Maybe a) -> (Int -> [a]) -> Int -> Maybe a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [a] -> [a]
    forall a. [a] -> [a]
    reverse ([a] -> [a]) -> (Int -> [a]) -> Int -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> [a]
    forall a. (Enum a, Bounded a, ToBitMask a) => Int -> [a]
    fromBitMask