How to provide generic type expressions in a where clause?

(please excuse the far-fetched example)

What I want to do is specify the types in the where-where:

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. 

If I just point out specific types, replacing Int with a and Bool with 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 constraint types in where-clause?

+7
source share
1 answer

Inside the where clause, variables of type a and b are variables of the new type; type variables are not limited, so each type signature has a new supply of them, as if they were defined at the top level.

If you enable the ScopedTypeVariables extension (put {-# LANGUAGE ScopedTypeVariables #-} at the top of your file) and change the declaration of somemap type to:

 somemap :: forall a b. (a -> b) -> [a] -> [b] 

then the where definitions you specified that you specify will work correctly. I think forall is only required for backward compatibility, so code that reuses type variables in where expressions for polymorphic values ​​is not interrupted.

If you do not want to use the extension, an alternative is to define ugly helper functions to unify types such as asTypeOf .

+15
source

All Articles