GHC / Hugs Disagree on Constraints
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
Hugs rejects it with +N -98 with
One fix is to bring type variables into the local scope, for example,
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound :: (LargeKey a b) = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
You still need -98 flag for Hugs. Another solution is totally Haskell98: introduce two functions
aoflk:: (LargeKey a b) -> a; aoflk = undefined boflk:: (LargeKey a b) -> b; boflk = undefined
then maxBound can be implemented as
maxBound = result where result = fromIntegral $ (1 + fromIntegral (maxBound `asTypeOf` (boflk result)))* (1 + fromIntegral (maxBound `asTypeOf` (aoflk result))) - 1
The apparent recursion in the above definition is superficial. The definition isn't actually recursive. We merely need the type of the 'result' rather than its value.
oleg@pobox.com wrote:
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
Hugs rejects it with +N -98 with
One fix is to bring type variables into the local scope, for example,
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound :: (LargeKey a b) = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
You still need -98 flag for Hugs. Another solution is totally Haskell98: introduce two functions
aoflk:: (LargeKey a b) -> a; aoflk = undefined boflk:: (LargeKey a b) -> b; boflk = undefined
then maxBound can be implemented as
maxBound = result where result = fromIntegral $ (1 + fromIntegral (maxBound `asTypeOf` (boflk result)))* (1 + fromIntegral (maxBound `asTypeOf` (aoflk result))) - 1
The apparent recursion in the above definition is superficial. The definition isn't actually recursive. We merely need the type of the 'result' rather than its value.
Oleg, Thanks for this. It seems strange that the scope of the universal quantifier is the function definition (in your first solution) rather than the whole of the instance. Is asTypeOf really Haskell 98? Dominic.
Dominic Steinitz asked:
Is asTypeOf really Haskell 98?
Yes, it is in the Prelude. And there is no special magic, it is Haskell-98-implementable, see http://haskell.org/onlinereport/standard-prelude.html#$vasTypeOf Bye Christian Sievers
oleg@pobox.com wrote:
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
Hugs rejects it with +N -98 with
One fix is to bring type variables into the local scope, for example,
instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, Bits b, Bounded b, Integral b, LargeWord b) => Bounded (LargeKey a b) where minBound = 0 maxBound :: (LargeKey a b) = fromIntegral $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1
You still need -98 flag for Hugs. Another solution is totally Haskell98: introduce two functions
aoflk:: (LargeKey a b) -> a; aoflk = undefined boflk:: (LargeKey a b) -> b; boflk = undefined
then maxBound can be implemented as
maxBound = result where result = fromIntegral $ (1 + fromIntegral (maxBound `asTypeOf` (boflk result)))* (1 + fromIntegral (maxBound `asTypeOf` (aoflk result))) - 1
The apparent recursion in the above definition is superficial. The definition isn't actually recursive. We merely need the type of the 'result' rather than its value.
Oleg, Did you get the first solution to work? When I tried it with hugs -98 I got ERROR "Codec/Encryption/LargeKey.hs":109 - Syntax error in input (unexpected `=') ghc with -fglasgow-exts accepts it. Dominic.
Dominic Steinitz wrote:
Did you get the first solution to work? When I tried it with hugs -98 I got
Yes, in the process discovering some interesting behavior of Hugs. Here's the complete code that works with Hugs
module Foo where
class Bits a
instance (Ord a, Bits a, Bounded a, Integral a, Bits b, Bounded b, Integral b) => Bounded (LargeKey a b) where minBound = 0 (maxBound :: (LargeKey a b)) = (fromIntegral::Int->(LargeKey a b)) $ (1 + fromIntegral (maxBound::b))* (1 + fromIntegral (maxBound::a)) - 1 data LargeKey a b = LargeKey a b deriving (Eq, Ord,Show) instance (Ord a, Eq a, Ord b, Show a, Show b) => Num (LargeKey a b) where (+) = undefined fromInteger = undefined
There are two interesting points: first, in order to add a type annotation to the result of a function, we have to place the whole function head in parenthesis, as in (maxBound :: (LargeKey a b)) = ... That does confuse GHC and cause it to give some quite weird error message. So, with parenthesis, it works in Hugs -98 but not in GHC. Without the parenthesis, it works the other way around. The other issue is an unnecessary type annotation on the function fromIntegral. GHC works well without that annotation. Alas, Hugs (November 2003) reports INTERNAL ERROR: findBtyvsInt The second solution seems better: not only it is in Haskell98, it also agrees with both Haskell systems.
participants (3)
-
Christian Sievers -
Dominic Steinitz -
oleg@pobox.com