Nicolas Trangez | 17 Nov 15:44 2012

Custom Enum instance with non-consecutive indices

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
(Continue reading)

Roman Cheplyaka | 17 Nov 15:52 2012

Re: Custom Enum instance with non-consecutive indices

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:
(Continue reading)

Nicolas Trangez | 17 Nov 16:23 2012

Re: Custom Enum instance with non-consecutive indices

On Sat, 2012-11-17 at 16:52 +0200, Roman Cheplyaka wrote:
> 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. 

Sure, but that kind-of defeats the purpose... fromEnum/toEnum would then
return some nonsensical integer value.

Nicolas
Herbert Valerio Riedel | 17 Nov 16:27 2012
Picon

Re: Custom Enum instance with non-consecutive indices

Nicolas Trangez <nicolas <at> incubaid.com> writes:

> On Sat, 2012-11-17 at 16:52 +0200, Roman Cheplyaka wrote:
>> 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. 
>
> Sure, but that kind-of defeats the purpose... fromEnum/toEnum would then
> return some nonsensical integer value.

...then don't derive an 'Enum' instance for that :-)

what do you hope to gain from making your flags type an instance of the
Enum class?
Nicolas Trangez | 17 Nov 16:30 2012

Re: Custom Enum instance with non-consecutive indices

On Sat, 2012-11-17 at 16:27 +0100, Herbert Valerio Riedel wrote:
> what do you hope to gain from making your flags type an instance of
> the
> Enum class? 

Among others, the ability to list all flags using "[Flag1 ..]"

How is this handled for libraries wrapping C libs which use some bitset
structure?

Nicolas
Roman Cheplyaka | 17 Nov 16:34 2012

Re: Custom Enum instance with non-consecutive indices

* Nicolas Trangez <nicolas <at> incubaid.com> [2012-11-17 16:23:28+0100]
> On Sat, 2012-11-17 at 16:52 +0200, Roman Cheplyaka wrote:
> > 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. 
> 
> Sure, but that kind-of defeats the purpose... fromEnum/toEnum would then
> return some nonsensical integer value.

What's your purpose, exactly? I see two of them — being able to use
enumerations, and converting from/to magical constants.

If you want to use toEnum/fromEnum for conversions so badly, you can
leave them as you defined them, but redefine the enumFrom* methods from
the Enum class.

But I'd still advise that you do your conversion outside of the Enum
class, since such instance would be very unintuitive to someone who
reads or uses your code.

BTW, the value of the derived fromEnum is not nonsensical — it
determines where in the [Flag1..] list a particular flag would appear.

Roman

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
(Continue reading)


Gmane