(please excuse the horribly contrived example)
What I want to do is specify types in the where-clause:
somemap :: (a -> b) -> [a] -> [b]
somemap f xs = ys
where
some = take 5 xs :: [a]
ys = map f some :: [b]
But this causes an error:
*Main> :load file.hs
[1 of 1] Compiling Main ( file.hs, interpreted )
fil.hs:15:18:
Couldn't match expected type `a1' against inferred type `a'
`a1' is a rigid type variable bound by
an expression type signature at file.hs:15:25
`a' is a rigid type variable bound by
the type signature for `somemap' at file.hs:12:12
Expected type: [a1]
Inferred type: [a]
In the second argument of `take', namely `xs'
In the expression: take 5 xs :: [a]
file.hs:16:13:
Couldn't match expected type `b1' against inferred type `b'
`b1' is a rigid type variable bound by
an expression type signature at file.hs:16:24
`b' is a rigid type variable bound by
the type signature for `somemap' at file.hs:12:17
In the first argument of `map', namely `f'
In the expression: map f some :: [b]
In the definition of `ys': ys = map f some :: [b]
Failed, modules loaded: none.
Whereas if I just specify concrete types, substituting Int for a and Bool for b, no problem:
somemap :: (Int -> Bool) -> [Int] -> [Bool]
somemap f xs = ys
where
some = take 5 xs :: [Int]
ys = map f some :: [Bool]
So my question is: How do I specify generic types and type constraints in a where-clause?
Inside the
whereclause, the type variablesaandbare new type variables; type variables aren’t scoped, so every type signature has a new supply of them, just as if they were defined at the top level.If you turn on the
ScopedTypeVariablesextension (put{-# LANGUAGE ScopedTypeVariables #-}at the top of your file), and changesomemap‘s type declaration to:then the
whereclause definitions you specified will work correctly. I think theforalls are only required for backwards compatibility, so that code that reuses type variables inwhereclauses for polymorphic values doesn’t break.If you don’t want to use an extension, the alternative is to define ugly helper functions to unify the types, like
asTypeOf.