Reputation: 395
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?
Upvotes: 13
Views: 1090
Reputation: 1918
The ScopedTypeVariables extension solves exactly your problem. The page also provides some alternative solutions (asTypeOf
and undefined
arguments).
Upvotes: 14