Is it impossible to calculate the difference between maxBound and minBound of type Enum?

Can we conclude that there is no way to calculate maxBound - minBound in Haskell for an arbitrary type of Enum and Bounded ? Or am I missing a trick / hack? This is what I have that obviously cannot work:

 difference :: (Enum a, Bounded a) => Int difference = fromEnum maxBound - fromEnum minBound 

Mistake:

 Foo.hs:37:1: Ambiguous constraint `Enum a' At least one of the forall'd type variables mentioned by the constraint must be reachable from the type after the '=>' In the type signature for `difference': difference :: (Enum a, Bounded a) => Int Foo.hs:37:1: Ambiguous constraint `Bounded a' At least one of the forall'd type variables mentioned by the constraint must be reachable from the type after the '=>' In the type signature for `difference': difference :: (Enum a, Bounded a) => Int 

I understand why I get this error - there is no real term with type a , so it cannot understand what a . The question is is there a way around this.

+8
haskell
source share
2 answers

Use Proxy to indicate which type you want, and use ScopedTypeVariables to enter this type in the scope of your function.

 {-# LANGUAGE ScopedTypeVariables #-} data Proxy a = Proxy difference :: forall a . (Enum a, Bounded a) => Proxy a -> Int difference Proxy = fromEnum (maxBound :: a) - fromEnum (minBound :: a) >>> difference (Proxy :: Proxy Bool) 1 

Edit: using the Daniel clause:

 data Proxy a = Proxy difference :: (Enum a, Bounded a) => Proxy a -> Int difference p = fromEnum (max' p) - fromEnum (min' p) where max' :: (Bounded a) => Proxy a -> a max' Proxy = maxBound min' :: (Bounded a) => Proxy a -> a min' Proxy = minBound 
+9
source share
 difference :: (Enum a, Bounded a) => a -> Int difference x = fromEnum (maxBound `asTypeOf` x) - fromEnum (minBound `asTypeOf` x) 

Name it, for example. difference (undefined :: Char) .

But note that this will be an overflow for some types (primarily Int ), so use the Integer result instead:

 difference :: (Enum a, Bounded a) => a -> Integer difference x = toEnum (fromEnum (maxBound `asTypeOf` x)) - toEnum (fromEnum (minBound `asTypeOf` x)) 
+12
source share

All Articles