Home > Software design >  Type deduce error for maxBound in a method with Constraints
Type deduce error for maxBound in a method with Constraints

Time:11-15

I'm going thru Get Programming with Haskell, and try to extend some examples. Having a problem for a function to get the maxBound of Enum:

rotGen :: (Bounded a, Enum a) => a -> (a, Int)
rotGen x = (x, fromEnum (maxBound))

Could not deduce (Bounded a0) arising from a use of ‘maxBound’ from the context: (Bounded a, Enum a)

I understand the problem - fromEnum (maxBound) can't figure out which Bounded type to get the bound. But I don't know to to let the compiler know it's the same type with x.

I tried fromEnum (maxBound :: a) - doesn't work.


Solved.

FYI. This is a cleaner implementation of the ROT13 rotator for Lesson 15 of the Get Programming with Haskell book:

-- gen encoder & decoder for enum 
rotGen :: forall a . (Bounded a, Enum a) => (a -> a, a -> a)
rotGen = (\x -> toEnum ((half   fromEnum x) `mod` max), \x -> toEnum ((upper   fromEnum x) `mod` max))
 where
    max = 1   fromEnum (maxBound @a)
    half = max `div` 2
    upper = max - half

(though as commented in the thread, language extension is too advanced for a newbie)

CodePudding user response:

You can work with the ScopedTypeVariables and TypeApplications extensions. In that case we define rotGen as:

{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}

rotGen :: forall a . (Bounded a, Enum a) => a -> (a, Int)
rotGen x = (x, fromEnum (maxBound @a))

With the ScopedTypeVariables we can make use of the type parameter a in the expression, and we should use an explicit forall. The TypeApplication extension will specify for what instance we use the maxBound constant.

CodePudding user response:

If you don't want to use extensions for some reason, you can use asTypeOf instead:

rotGen x = (x, fromEnum (maxBound `asTypeOf` x))
  • Related