[Haskell-cafe] Custom Enum instance with non-consecutive indices

Roman Cheplyaka roma at ro-che.info
Sat Nov 17 15:52:53 CET 2012


Hi Nicolas,

The simplest approach would be to use the standard (derived) Enum
instance that would be used for enumerations (like [Flag1..]), and
have your own functions to convert to/from magic constants.

Roman

* Nicolas Trangez <nicolas at incubaid.com> [2012-11-17 15:44:57+0100]
> All,
> 
> I've been working on a server implementation of an existing networking
> protocol. The protocol uses "magic constants" in some places (e.g. to
> tag message types), as well as bitfields, or a combination of both
> packed in a single value.
> 
> I created data types for both the identifiers as well as the bitfield
> masks, e.g.
> 
> > import Data.Bits
> 
> > data MessageType = Message1
> >                  | Message2
> >                  | Message5
> 
> > data MessageFlag = Flag1
> >                  | Flag2
> 
> Since I need to be able to get a numeric representation of them, I
> thought making a custom Enum instance would make sense:
> 
> > instance Enum MessageType where
> >     fromEnum a = case a of
> >         Message1 -> 1
> >         Message2 -> 2
> >         Message5 -> 5
> >     toEnum n
> >         | n == 1 = Message1
> >         | n == 2 = Message2
> >         | n == 5 = Message5
> 
> > instance Enum MessageFlag where
> >     fromEnum a = case a of
> >         Flag1 -> 1 `shiftL` 0
> >         Flag2 -> 1 `shiftL` 1
> >     toEnum n
> >         | n == 1 `shiftL` 0 = Flag1
> >         | n == 1 `shiftL` 1 = Flag2
> 
> This is not a complete definition (not to mention non-exhaustive pattern
> matches), so I was wondering what the best practices are to extend this
> so these instances are 'correct'?
> 
> I've been trying several approaches, but all of them failed on code like
> 
> > getFlags :: Int -> [MessageFlag]
> > getFlags i = filter (\v -> (i .&. fromEnum v) /= 0) [Flag1 ..]
> 
> Unless I hard-code all options in the last list, of course, but this is
> obviously not the intention.
> 
> Any help or pointers (including "This is not how Enum is intended to be
> used") would be appreciated!



More information about the Haskell-Cafe mailing list