Consider the following snipet
-- This compiles
import Control.Monad
v :: Monad m => m b
v = undefined
w :: Monad m => m c
w = undefined
h :: Monad m => a -> m c
h = v' >=> w'
where v' :: Monad m1 => a -> m1 b
v' = const v
w' :: Monad m2 => b -> m2 c
w' = const w
It compiles fine and is able to solve m ~ m1 ~ m2, but if we bring v and w into h scope, then it wont compile any more: Couldn't match type `m1' with `m'
-- This doesn't compiles but looks equivalent to h
h' :: Monad m => m b -> m c -> a -> m c
h' v w = v' >=> w'
where v' :: Monad m1 => a -> m1 b
v' = const v
w' :: Monad m2 => b -> m2 c
w' = const w
I would think that both h and h' are equivalent when type resolution comes into play, since not in h nor h' assumptions over m are made. But it turns out that h' needs the help of ScopedTypeVariables to specify the m ~ m1 ~ m2
I seems weird that GHC does not complain in the h but is does in h'. Why ScopedTypeVariables is needed to compile h' but it isn't to compile h?
For the record
Just in case you wonder this is the version of h' which compiles. But notice the question is why ScopedTypeVariables is not needed to compile h? instead of why ScopedTypeVariables is needed to compile h'?
{-# LANGUAGE ScopedTypeVariables #-}
h' :: forall m a b c. Monad m => m b -> m c -> a -> m c
h' v w = v' >=> w'
where v' :: Monad m => a -> m b
v' = const v
w' :: Monad m => b -> m c
w' = const w