Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting enumerations to int-like types in haskell

Tags:

enums

haskell

I was following the advice on Haskell's Wiki page: Performance/Data types to improve the performance of my code, but when I changed

data Color = Yellow | Red | Green | Blue | Empty deriving (Show, Eq)

to

newtype Color = Color Int deriving (Eq,Ord,Enum) 
(yellow:red:green:blue:empty:_) = [Color 1 ..]

as suggested in the article, GHC says:

Can't make a derived instance of `Enum Color':
  `Color' must be an enumeration type
  (an enumeration consists of one or more nullary, non-GADT constructors)
  Try -XGeneralizedNewtypeDeriving for GHC's newtype-deriving extension
In the newtype declaration for `Color'

I haven't worked with Enums much, how do I turn Color into an Enum type? Do I have to implement all the functions it defines? I thought they were all implemented when you derived that class.

like image 749
Drew Avatar asked Dec 07 '12 10:12

Drew


2 Answers

Sometimes GHC's advice is bad, but in this case it's spot on. At the top of your file, put

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

GeneralizedNewtypeDeriving is a language extension that allows you to specify that some classes should be "forwarded" to their representation's instances. That is, newtype Color = Color Int deriving (Enum) says to implement Color's Enum instance just by using Int's (after some necessary wrapping/unwrapping, which GHC generates for you).

But if this is the only reason you need Enum, you could also omit it and just do

(yellow:red:green:blue:empty:_) = map Color [1..]
like image 168
luqui Avatar answered Oct 24 '22 10:10

luqui


Note that by deriving Enum you'll get only a partially correct implementation. For example, enumFrom yellow will return a list equivalent to map Color $ [1..], which is probably not what you want.

So I'd rather suggest to implement Enum together with Bounded manually so that it satisfies rules given in the documentation of Enum.

I suppose all this stuff could be generated automatically with Template Haskell. This would make an interesting library.

like image 4
Petr Avatar answered Oct 24 '22 10:10

Petr