<div dir="ltr">Note that this also requires ScopedTypeVariables; the Haskell standard specifies that type variables are only in scope within the type signature, not the accompanying binding. Which is also why the explicit "forall" is required, to tell it to use the modified rules here, which otherwise could cause other code that expects standard Haskell behavior to fail to compile if it happens to reuse type variables from the signature.</div><br><div class="gmail_quote"><div dir="ltr">On Fri, Aug 24, 2018 at 5:37 PM mniip <<a href="mailto:14@mniip.com">14@mniip.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> • Found type wildcard ‘_c’ standing for ‘c’<br>
>    Where: ‘c’ is a rigid type variable bound by<br>
>             the type signature for:<br>
>               f1 :: forall (m :: * -> *) c. MonadIO m => c -> m Bool<br>
>             at Test.hs:15:1-32<br>
<br>
Emphasis on "rigid". It's not telling you to introduce a new type<br>
variable and put that there. It's telling you that the type you need to<br>
put there is an existing type variable's type.<br>
<br>
When you write 'run :: MS c Int a -> (Either String a, Int)' you<br>
implicitly mean 'run :: forall c.' which is exactly introducing a new<br>
type variable.<br>
<br>
> • Couldn't match type ‘c1’ with ‘c’<br>
>    ‘c1’ is a rigid type variable bound by<br>
>      the type signature for:<br>
>        run :: forall c1 a. MS c1 Int a -> (Either String a, Int)<br>
This is the 'c' you bound with the implicit 'forall'. The compiler is<br>
asked to verify that 'run' indeed works 'forall c1', so during<br>
typechecking of the function body the 'c1' variable is also rigid.<br>
<br>
>    ‘c’ is a rigid type variable bound by<br>
>      the type signature for:<br>
>        f1 :: forall (m :: * -> *) c. MonadIO m => c -> m Bool<br>
This is the 'c' from the typed hole suggestion up above, still rigid.<br>
<br>
A part of the typechecking algorithm is that two rigid type variables<br>
cannot be equated.<br>
<br>
The solution *actually* proposed by GHC in the wildcard suggestion is to<br>
use the 'c' variable from 'f1's type for which you need to make it<br>
scoped with an explicit 'forall':<br>
<br>
        f1 :: forall c. (MonadIO m) => c -> m ()<br>
        f1 c = do<br>
          let _x1 = run f2<br>
          let _x2 = run f3<br>
          return ()<br>
          where<br>
            run :: MS c Int a -> (Either String a, Int)<br>
            run = runMS c 0<br>
            f2 :: MS c s Bool<br>
            f2 = pure False<br>
            f3 :: MS c s [Int]<br>
            f3 = pure []<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>brandon s allbery kf8nh</div><div><a href="mailto:allbery.b@gmail.com" target="_blank">allbery.b@gmail.com</a></div></div></div></div></div>