Better Way to Define an Enum in Haskell

haskell toenum
enum class haskell
haskell enum from string
haskell ord
haskell deriving
haskell instances
haskell define a set
haskell fromenum

I want a datatype to represent a finite set of integers that can be addressed by specific names. I figure the best way to do that is to use an Enum.

However, there is one small problem. The only way I know for defining an Enum is something like this:

data MyDataType = Foo | Bar | Baz

instance Enum MyDataType 
 toEnum 0 = Foo
 toEnum 1 = Bar
 toEnum 2 = Baz

 fromEnum Foo = 0
 fromEnum Bar = 1
 fromEnum Baz = 2 

Note that I have to repeat the same pair two times - one time when defining an integer-to-enum mapping and the other time when defining an enum-to-integer mapping.

Is there a way to avoid this repetition?

instance Enum MyDataType where
    fromEnum = fromJust . flip lookup table
    toEnum = fromJust . flip lookup (map swap table)
table = [(Foo, 0), (Bar, 1), (Baz, 2)]

Making Our Own Types and Typeclasses, Well, one way is to use the data keyword to define a type. A better solution would be to make our own type to represent a shape. make our type an instance of any of the following typeclasses: Eq, Ord, Enum, Bounded, Show, Read. ZVON > References > Haskell reference: Intro / Search / ZVON instance Enum Float where succ x = x+1 pred x = x-1 toEnum = fromIntegral fromEnum = fromInteger.

data MyDataType = Foo | Bar | Baz deriving (Enum)

6 Predefined Types and Classes, When appropriate, the Haskell definition of the type is given. Some Type Char is an instance of the classes Read, Show, Eq, Ord, Enum, and The Prelude contains a few I/O functions (defined in Section 9.3), and Part II contains many more. Firstly, for existing Enums: instance Enum Blah. Will completely define Blah as an Enum if Blah is already a Prelude style Enum, just forwarding calls to the functions in the Prelude's Enum. Secondly, for integral datatypes (i.e. in class Integral) instance Enum Blah type EnumNumT Blah = Blah. will defined Blah to be an Enum, with it's Enum

The problem with the accepted solution is the compiler won't tell you when you are missing an enum in your table. The deriving Enum solution is great, but it won't work if you want to have an arbitrary mapping to numbers. Another answer suggests Generics or Template Haskell. This follows up on that by using Data.

{-# Language DeriveDataTypeable #-}
import Data.Data
data MyDataType = Foo | Bar | Baz deriving (Eq, Show, Data, Typeable)

toNumber enum = case enum of
   Foo -> 1
   Bar -> 2
   Baz -> 4

We will get compiler warning in the toNumber case mapping when a new constructor is added.

Now we just need the ability to turn that code into data so that the mapping can be automatically reversed. Here we generate the same table mentioned in the accepted solution.

table = map (\cData -> let c = (fromConstr cData :: MyDataType) in (c, toNumber c) )
      $ dataTypeConstrs $ dataTypeOf Foo

You can fill out an Enum class just the same as in the accepted answer. Unmentioned there is that you can also fill out the Bounded class.

GHC.Enum - Hackage, See Chapter 10 of the /Haskell Report/ for more details. 'enumFrom' and '​enumFromThen' should be defined with an implicit bound, -- thus: Int# ord# Char# y) -- See Note [How the Enum rules work] {-# RULES "eftChar" [~1] forall x y. class Enum a where pred, there is a standard way to define instances. The Haskell compiler knows how to define these instances. Better than random testing!

Since you say the numbers are not generated by any regular law, you could use generic programming (e.g. with Scrap Your Boilerplate) or Template Haskell to implement a generic solution to this problem. I tend to prefer Template Haskell because it actually generates code and compiles it, so you get all the type-checking and optimisation benefits of GHC.

I wouldn't be surprised if someone had implemented this already. It should be trivial.

Write C-style enum in Haskell · GitHub, The Haskell way to define C-style enum type. An enumerator with = defines its enumeration constant as the value of the constant expression. If the first  (the other constraints have no preconditions) so in order to use mod and div the type has to be Num, Eq, Ord, Enum, Real, and Integral, as this is the typeclass hierarchy set up in Haskell. The two built-in types that fit these constraints are Int and Integer .

My examples here are using GHCI 8.4.4 with a prompt, "λ: ".

I think deriving from Enum makes the most sense here, as the most fundamental types in Haskell also derive from Enum (tuples, characters, integers, etc...), and it has builtin methods of getting values into and from the enum.

First, create a data type deriving Enum (and Show so you can view the value in the REPL and Eq to enable .. range completion):

λ: data MyDataType = Foo | Bar | Baz deriving (Enum, Show, Eq)
λ: [Foo ..]
[Foo,Bar,Baz]

Enums define a method, fromEnum, which you can use to get the values as requested in the question (0, 1, and 2).

Usage:

λ: map fromEnum [Foo ..]
[0,1,2]

It is a simple matter to define a function giving an arbitrary value (such as powers of two using the integer power operator, ^):

λ: value e = 2 ^ (fromEnum e)

Usage:

λ: map value [Foo ..]
[1,2,4]

Another answer says:

The deriving Enum solution is great, but it won't work if you want to have an arbitrary mapping to numbers.

Well, let's see about that (use :set +m to enable multiline input in GHCI, if you haven't already):

arbitrary e = case e of
  Foo -> 10
  Bar -> 200
  Baz -> 3000

Usage:

λ: map arbitrary [Foo ..]
[10,200,3000]

We just demonstrated that it does indeed work, but I would prefer to calculate it from the fromEnum as we did with value, if we do not want values increasing by 1 from 0.

The Haskell 1.3 Report: Basic Types and Classes, I want a datatype to represent a finite set of integers that can be addressed by specific names. I figure the best way to do that is to use an Enum. However, there​  Program source: data XXX = AA|BB|CC|DD deriving (Enum, Show). Input: fromEnum BB Output: 1 1

Haskell/More on datatypes, When appropriate, the Haskell definition of the type is given. The name otherwise is defined as True to make guarded expressions more readable. Type Char is an instance of the classes Read, Show, Eq, Ord, Enum, and Bounded. But the programmer is currently forced to define a method for (*) when she defines a method for (+). In specifying the semantics of type classes, I will state laws as follows: (a + b) + c === a + (b + c) The intended meaning is extensional equality: The rest of the program should behave in the same way if one side is replaced with the other.

Type Classes, Named Fields (Record Syntax)Edit. Consider a datatype whose purpose is to hold configuration settings. Usually, when you extract members from this type, you  Class Enum defines operations on sequentially ordered types. The functions succ and pred return the successor and predecessor, respectively, of a value. The functions fromEnum and toEnum map values from a type in Enum to and from Int. The enumFrom methods are used when translating arithmetic sequences (Section 3.10).

The Haskell 98 Report: Basic Types and Classes, For example, here is the definition of the Maybe type that we've used in past Either String a works a little better - you can use Left msg in the case of an Here's one way to define binary trees that have data at the internal nodes in Haskell: class Enum a where succ, pred :: a -> a toEnum :: Int -> a fromEnum :: a -> Int  There must be a better way, you say! Well no, there isn't, sorry. Just kidding, there is. Hahaha! The makers of Haskell were very smart and anticipated this scenario. They included an alternative way to write data types. Here's how we could achieve the above functionality with record syntax.

Comments
  • Do you know about deriving Enum ? It is magical!
  • Ok, but it probably will not work if the values that are assigned to the names are not sequential, e.g. Foo should be 2, Bar should be 4, Baz should be 8, etc.
  • Aside from Augustss's suggestion, a method I've used is to derive Enum and place filler types in the gaps (when the gaps are small): data SomeEnum = ValueA | Reserved1 | Reserved2 | ValueB | Reserved3 | ValueC
  • Something to note, though - long hand, as per the code in the question, is both efficient and clear. Sometimes scraping boilerplate isn't the best path.
  • If the values you want are in fact 2, 4, 8, 16, etc. it seems to me there might be another way. Like, use deriving Enum, but then write your own version of the toEnum' and fromEnum' which call toEnum and fromEnum and then do the 2^x conversion. Whether this is any better, I don't know.
  • ...where swap is the obvious swap (x,y) = (y,x) (defined in Data.Tuple in the latest Haskell Platform)
  • I know I am not supposed to care, but will this be optimized into something efficient by ghc?
  • @Florian, probably not. It's possible to write similar things that probably will be.
  • will GHC at least realise to only generate the swapped table (map swap table) once?
  • Good for sequential enum values (like in my example), but will it work if the values are not sequential (e.g. Foo should be 2, Bar should be 4, and so on?)
  • Not directly - but if you can write a bijective function f which turns the consecutive integers from 0..n into the integers you want, you can define a newtype MyRealDataType = MyRealDataType MyDataType and give it an Enum instance which "corrects" the values produced by the Enum instance of MyDataType. The disadvantage is you have to unwrap it when you want to pattern match directly on the names, etc.
  • Problem is, there is no specific law according to which the values change (they are not powers of 2, for example).
  • OK, I should have thought of augustss's solution. The only advantage of this one is that you don't need to list out all the constructor names twice.
  • And yours gets optimized.and checked properly.