module Extra where
import Ix
import Data.Set(Set,toList)

{-+
Here is a convenient way to obtain a list of all values of a given type,
e.g. all states in a model.
-}
enumAll :: (Bounded a,Ix a) => [a]
enumAll = range (minBound,maxBound)

{-+
The #ShowBits# class provides a way to print bit vectors, represented
as tuples of booleans, in a compact and readable way, e.g. #010# instead of
 #(False,(True,False))#
-}
class ShowBits s where showBits :: s -> ShowS

{-+ Single booleans are shown as 0 and 1 instead of False and True. -}
instance ShowBits Bool where showBits = shows . fromEnum

{-+ Pairs of bit vectors are just concatenated. -}
instance (ShowBits a,ShowBits b) => ShowBits (a,b) where
  showBits (a,b) = showBits a . showBits b

{-+ When showing a list or a set of bit vectors, the elements are
    separated by spaces.-}
instance ShowBits a => ShowBits [a] where
  showBits = foldr (\x r->showBits x.(' ':).r) id

instance ShowBits a => ShowBits (Set a) where
  showBits = showBits . toList

{-+ Use #B v# if you want to display a bit vector #v# in the compact
readable way.
-}
newtype B a = B a

instance ShowBits a => Show (B a) where
  showsPrec _ (B a) = showBits a


{-+ A type for transitions and a nice way to show them -}
data Trans s1 s2 = s1 :-> s2

instance (ShowBits s1,ShowBits s2) => Show (Trans s1 s2) where
  showsPrec _ (s1:->s2) = showBits s1 . (" -> "++) . showBits s2
  showList = showsLines

showsLines xs r = foldr showsLine r xs
  where showsLine x r = shows x ('\n':r)