[Haskell] GHC / Hugs Disagree on Constraints
Simon PeytonJones
simonpj at microsoft.com
Mon Oct 4 04:13:24 EDT 2004
Hugs does support scoped type variables bound by *type sigs in
patterns*, but not by class or instance declarations. So when you say
(maxBound :: b)
you are really saying
(maxBound :: forall b. b)
and it's that universal quantification that has no Bounded b context.
That's why you need fglasgowexts to compile it with GHC, to get the
scoped type variables.
I've gotten so used to scoped type variables that I couldn't see why it
wasn't Haskell 98, until I tried to compile without fglasgowexts.
Then GHC says
Key.hs:99:
Could not deduce (Bounded b) from the context ()
arising from use of `maxBound' at Key.hs:99
Probable fix:
Add (Bounded b) to the expected type of an expression
When checking the type signature of the expression:
maxBound :: forall b. b
which does at least point to the error.
Simon
 Original Message
 From: haskellbounces at haskell.org [mailto:haskellbounces at haskell.org]
On Behalf Of Dominic
 Steinitz
 Sent: 02 October 2004 12:04
 To: haskell at haskell.org
 Subject: [Haskell] GHC / Hugs Disagree on Constraints

 GHC accepts this with fglasgowexts

 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

 ERROR "Codec/Encryption/LargeKey.hs":94  Cannot justify constraints
in
 type annotation
 *** Expression : maxBound
 *** Type : b
 *** Given context : ()
 *** Constraints : Bounded b

 Since I've already declared b to be Bounded, it looks like a bug in
Hugs.

 Dominic.

 ===============================================================
 ========

 module Codec.Encryption.LargeKey
 (Word128,Word192,Word256,LargeWord) where

 import Data.Word
 import Data.Bits
 import Numeric
 import Char

  Keys have certain capabilities.

 class LargeWord a where
 largeWordToInteger :: a > Integer
 integerToLargeWord :: Integer > a
 largeWordPlus :: a > a > a
 largeWordAnd :: a > a > a
 largeWordOr :: a > a > a
 largeWordShift :: a > Int > a
 largeWordXor :: a > a > a
 largeBitSize :: a > Int

  Word64 is a key in the obvious way.

 instance LargeWord Word64 where
 largeWordToInteger = toInteger
 integerToLargeWord = fromInteger
 largeWordPlus = (+)
 largeWordAnd = (.&.)
 largeWordOr = (..)
 largeWordShift = shift
 largeWordXor = xor
 largeBitSize = bitSize

  Define larger keys from smaller ones.

 data LargeKey a b = LargeKey a b
 deriving (Eq, Ord)

 instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) =>
 LargeWord (LargeKey a b) where
 largeWordToInteger (LargeKey lo hi) =
 largeWordToInteger lo + (2^(bitSize lo)) *
largeWordToInteger hi
 integerToLargeWord x =
 let (h,l) = x `quotRem` (2^(bitSize lo))
 (lo,hi) = (integerToLargeWord l, integerToLargeWord h)
in
 LargeKey lo hi
 largeWordPlus (LargeKey alo ahi) (LargeKey blo bhi) =
 LargeKey lo' hi' where
 lo' = alo + blo
 hi' = ahi + bhi + if lo' < alo then 1 else 0
 largeWordAnd (LargeKey alo ahi) (LargeKey blo bhi) =
 LargeKey lo' hi' where
 lo' = alo .&. blo
 hi' = ahi .&. bhi
 largeWordOr (LargeKey alo ahi) (LargeKey blo bhi) =
 LargeKey lo' hi' where
 lo' = alo .. blo
 hi' = ahi .. bhi
 largeWordOr (LargeKey alo ahi) (LargeKey blo bhi) =
 LargeKey lo' hi' where
 lo' = alo .. blo
 hi' = ahi .. bhi
 largeWordXor (LargeKey alo ahi) (LargeKey blo bhi) =
 LargeKey lo' hi' where
 lo' = alo `xor` blo
 hi' = ahi `xor` bhi
 largeWordShift w 0 = w
 largeWordShift (LargeKey lo hi) x =
 if bitSize lo < bitSize hi
 then LargeKey (shift lo x)
 (shift hi x .. (shift (conv lo) (x 
 (bitSize lo))))
 else LargeKey (shift lo x)
 (shift hi x .. (conv $ shift lo (x 
 (bitSize lo))))
 where conv = integerToLargeWord . largeWordToInteger
 largeBitSize ~(LargeKey lo hi) = largeBitSize lo + largeBitSize
hi

 instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) => Show
 (LargeKey a b) where
 showsPrec p = showInt . largeWordToInteger

 instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) =>
 Num (LargeKey a b) where
 (+) = largeWordPlus
 fromInteger = integerToLargeWord

  Larger keys are instances of Bits provided their constituents are
keys.

 instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) =>
 Bits (LargeKey a b) where
 (.&.) = largeWordAnd
 (..) = largeWordOr
 xor = largeWordXor
 shift = largeWordShift
 bitSize = largeBitSize

 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

 instance (Ord a, Bits a, LargeWord a, Ord b, Bits b, LargeWord b) =>
 Integral (LargeKey a b) where
 toInteger = largeWordToInteger

 instance (Ord a, Bits a, LargeWord a, Ord b, Bits b, LargeWord b) =>
 Real (LargeKey a b)

 instance Enum (LargeKey a b)

 type Word96 = LargeKey Word32 Word64
 type Word128 = LargeKey Word64 Word64
 type Word160 = LargeKey Word32 Word128
 type Word192 = LargeKey Word64 Word128
 type Word224 = LargeKey Word32 Word192
 type Word256 = LargeKey Word64 Word192
 _______________________________________________
 Haskell mailing list
 Haskell at haskell.org
 http://www.haskell.org/mailman/listinfo/haskell
More information about the Haskell
mailing list