Is there some way to define an Enum in haskell that wraps around?

haskell record syntax
haskell deriving
haskell flexibleinstances
define datatype haskell
haskell algebraic data types
haskell sum type
haskell data types
define algebraic data type

Consider I was designing a Monopoly game:

data Board = GO | A1 | CC1 | A2 | T1 | R1 | B1 | CH1 | B2 | B3 | 
  JAIL | C1 | U1 | C2 | C3 | R2 | D1 | CC2 | D2 | D3 | 
  FP | E1 | CH2 | E2 | E3 | R3 | F1 | F2 | U2 | F3 | 
  G2J | G1 | G2 | CC3 | G3 | R4 | CH3 | H1 | T2 | H2
  deriving (Show, Enum, Eq)

I want:

succ H2 == GO

But instead:

*** Exception: succ{Board}: tried to take `succ' of last tag in enumeration

Is there a typeclass for expressing an enumeration that wraps around?

The simplest option is to make Board an instance of Bounded (can be auto derived as well), and use the following helper functions:

next :: (Enum a, Bounded a) => a -> a
next = turn 1

prev :: (Enum a, Bounded a) => a -> a
prev = turn (-1)

turn :: (Enum a, Bounded a) => Int -> a -> a
turn n e = toEnum (add (fromEnum (maxBound `asTypeOf` e) + 1) (fromEnum e) n)
    where
      add mod x y = (x + y + mod) `rem` mod

Example Use:

> next H2
G0
> prev G0
H2
> next F1
F2

(inspired by the the thread at http://www.mail-archive.com/haskell-cafe@haskell.org/msg37258.html ).

If you really need to use succ and pred instead, I don't believe there is any laws regarding implementations of Enum such that succ (succ x) /= x for all x (even though that is how most work). Therefore you could just write a custom implementation of Enum for your type that exhibits the wraparound you desire:

instance Enum Board where
  toEnum 0 = G0
  toEnum 1 = A1
  ...
  toEnum 40 = H2
  toEnum x = toEnum (x `mod` 40)

  fromEnum G0 = 0
  fromEnum A1 = 1
  ...
  fromEnum H2 = 40

That is very tedious to implement though. Also, the type shouldn't also implement Bounded when using a circular definition of Enum, as that breaks a rule regarding Bounded that succ maxBound should result in a runtime error.

Beginning Haskell: A Project-Based Approach, These list types will all ultimately be founded on some instance of the type [(a,b)] Set functions such as nub and sorting functions such as sort work in that same way. As an example, let's define a function enum that generates a list of numbers. the key implies that the returned value is wrapped on a Maybe.3 *​Chapter3. Program source: data XXX = AA|BB|CC|DD deriving (Enum, Show). Input: fromEnum BB Output: 1 1

A simpler solution than nanothief:

nextBoard :: Board -> Board
nextBoard H2 = GO
nextBoard t = succ t

I don't think you'll be able to use Enum directly for what you want, but this solution quickly wraps it to form the behaviour you want.

Is there a way to plus one to an Enum Bounded Ord type in a list in , You can make a wrapping succ for Bounded and Enum types: succWrap x = if x == maxBound then minBound else succ x. then you need just Also, some of the standard classes are part of the standard Haskell libraries; these are described in the Haskell Library Report. 8.1 Equality and Ordered Classes. The classes Eq and Ord have already been discussed. The definition of Ord in the Prelude is somewhat more complex than the simplified version of Ord presented earlier.

I know this is an old question but I just had this problem and I solved it this way.

data SomeEnum = E0 | E1 | E2 | E3
               deriving (Enum, Bounded, Eq)

-- | a `succ` that wraps 
succB :: (Bounded a, Enum a, Eq a) => a -> a 
succB en | en == maxBound = minBound
         | otherwise = succ en

-- | a `pred` that wraps
predB :: (Bounded a, Enum a, Eq a) => a -> a
predB en | en == minBound = maxBound
         | otherwise = pred en  

The solution derives both Enum and Bounded but avoids abusing pred and succ as suggested.

Incidently, I found that having

allSomeEnum = [minBound..maxBound] :: [SomeEnum] 

can be useful. That requires Bounded.

Exploring C++: The Programmer's Introduction to C++, (Or a lot of extra work, depending on how fancy you want your simulation to be.) Do you stick at the limit, wrap to the other limit, or throw an exception? For example, let's define an enumeration of computer programming languages. associated information. class language { public: enum type { apl; c, Cpp, forth, haskell,  Thanks to higher order functions Haskell gives you very many opportunities to factor out parts of the code. If you find the function very general, put it in a separate module and re-use it. It may appear in the standard libraries later, or you may later find that it is already there in an even more general way.

There is a disgusting way to define an efficient wrapping Enum instance without doing much by hand.

{-# LANGUAGE MagicHash #-}

import GHC.Exts (Int (..), tagToEnum#, dataToTag# )

-- dataToTag# :: a -> Int#
-- tagToEnum# :: Int# -> a

Now you can write

data Board = ... deriving (Eq, Ord, Bounded)

instance Enum Board where
  fromEnum a = I# (dataToTag# a)

  toEnum x | x < 0 || x > fromEnum (maxBound :: Board) =
    error "Out of range"
  toEnum (I# t) = tagToEnum# t
  succ x | x == maxBound = minBound
         | otherwise == toEnum (fromEnum x + 1)
  pred x ....

Real World Haskell: Code You Can Believe In, The final part of the #enum syntax is self-explanatory: it just defines Haskell Running this code through hsc2hs, as before, generates a Haskell file with the The final accumulated state is then wrapped up in the PCREOption constructor. enummapset-th: TH-generated EnumSet/EnumMap wrappers around IntSet/IntMap. [ bsd3 , data , library ] [ Propose Tags ] This package wraps IntSet and IntMap from containers , and provides fast sets and maps keyed on any data type with a well-behaved Enum instance.

With Eq you can check if it's the last element.

next :: (Eq a, Enum a, Bounded a) => a -> a
next = bool minBound <$> succ <*> (/= maxBound)

Algebraic Data Types, In Haskell, the keyword data introduces the definition of a data type. Values of enumeration types are often scrutinised by way of pattern matching. which are identical except for their rotation around their center, we start with a list of we may regard data constructors as a special kind of function, a function that wraps its  Program source: data XXX = AA|BB|CC|DD deriving (Enum, Show). Input: toEnum 0::XXX Output: AA AA

9.1. Language options, You cannot define a newtype whose representation type (the argument type This extension also relaxes some of the restrictions around data family instances. They are a convenient way of pattern-matching against values of abstract types​. we would like the knots to be wrapped around as minimal groups as possible. instance Enum Float where succ x = x+1 pred x = x-1 toEnum = fromIntegral fromEnum = fromInteger. truncate -- may overflow enumFrom = numericEnumFrom enumFromThen = numericEnumFromThen enumFromTo = numericEnumFromTo enumFromThenTo = numericEnumFromThenTo

Why isn't Bounded a subclass of Enum in Haskell, One practical example I like comes from the world of programming languages: the set of types in an OO system is bounded and discrete but not  However, arbitrary #define cannot be imported this way. Some preprocessor macros have parameters, or contain C statements, or otherwise cannot be assignment expression's RHS. To rule such preprocessor macros out, for each #define hsffig encounters on its input, a short C program is created, like this: #include "header.h" static int a = BIG_ENDIAN;

Chapter 6. Using Typeclasses, Typeclasses define a set of functions that can have different implementations depending on the Let's see what it says about isEqual : No comments You can read that this way: "For all types a , so long as a is an instance of BasicEq automatically derive instances of Read , Show , Bounded , Enum , Eq , and Ord for us. This type of recursion is a very common pattern in Haskell. Type and newtype. The other two ways one may introduce types to Haskell programs are via the type and newtype statements. type introduces a synonym for a type and uses the same data constructors. newtype introduces a renaming of a type and requires you to provide new constructors.

Comments
  • Huh, Enum. You just need to write your own instead of deriving it automatically.
  • I recommend against making succ maxBound = minBound; the Bounded typeclass explicitly says that succ maxBound should result in a runtime error.
  • This still doesn't let you do, say [H1 .. A1], which should logically be equal to [H1, T2, H2, GO, A1].
  • @Edward: The second solution doesn't have Board an instance of Bounded, so that problem doesn't occur. I'll make that more explicit that the type cannot be Bounded when implementing Enum that way in the answer though.
  • Ah, I suppose, then, that this is OK. :-)