ScopedTypeVariables
let you refer to universally quantified types inside of a declaration. To be more explicit:
import Data.Monoid
foo :: forall a b c. (Monoid b, Monoid c) => (a, b, c) -> (b, c) -> (a, b, c)
foo (a, b, c) (b', c') = (a :: a, b'', c'')
where (b'', c'') = (b <> b', c <> c') :: (b, c)
The important thing is that we can use a
, b
and c
to instruct the compiler in subexpressions of the declaration (the tuple in the where
clause and the first a
in the final result). In practice, ScopedTypeVariables
assist in writing complex functions as a sum of parts, allowing the programmer to add type signatures to intermediate values that don't have concrete types.