[Haskell] GHC / Hugs Disagree on Constraints

Dominic Steinitz dominic.steinitz at blueyonder.co.uk
Sat Oct 2 07:04:03 EDT 2004


GHC accepts this with -fglasgow-exts

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


More information about the Haskell mailing list