I have a problem relating to the Haskell type system. This is not the first time I have encountered the type system's limitations. I will omit my project details and use a simplified example. Here is some code:
-- Works
foo :: (Bounded a, Enum a) => a
foo = minBound
-- "ambiguous" constraint:
-- 'a' has no occurrences in type declaration
bar :: (Bounded a, Enum a) => Int
bar = fromEnum minBound
-- Too much information in return
-- but I can show haskell the appropriate type of 'min'
baz :: (Bounded a, Enum a) => (a, Int)
baz = let min = minBound
in (min, someFunction . fromEnum $ min)
-- Type constraint 'a' not ambiguous
-- (or at least that isn't the compiler error message)
-- but Haskell doesn't know which 'minBound' to use
barrer :: (Bounded a, Enum a) => a
barrer = let min = minBound -- <- min's type is ambiguous
in toEnum . someFunction . fromEnum $ min
What I am trying to achieve is similar to barrer
: First, use the minBound
value specific to type a
and 'cast' it to an integer. In my project, I proceed to transform this integer (to avoid intermediate arithmetic overflows when using type a
) and 'cast' them back to type a
(after a bit of mod
magic). How can I tell Haskell the appropriate type of minBound
? Is it possible?
The obvious solution is to add an annotation of minBound :: a
. This would also fix bar
. The problem: The type variable a
seems to be out of scope in the function definition, as Haskell freshens minBound :: a
to minBound a0
in the error message. Is there a way to do this type of annotation?
One bad hack I used was to constrain the type of the minBound
call by including it in the function's return type, a la baz
. This solution is not ideal. Does anyone have some advise?
The ScopedTypeVariables extension solves exactly your problem. The page also provides some alternative solutions (asTypeOf
and undefined
arguments).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With