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))