<div dir="ltr"><div><div>As to your original code, the only actual bug is that someA :: a is wrong.  The actual type of someA is someA :: C a => a, so you could have written<br><br></div><div>class C a where<br>  someA :: a<br><br>f :: C a => a -> Int<br>f a =<br>  let x :: C a => a<br>      x = someA -- absolutely works<br>  in 0<br><br><br></div><div>But remember that in x, 'a' is not the same as the 'a' in f, so you might as well have written this<br><br></div><div>  f :: C a => a -> Int<br>
  f a =<br>
    let x :: C b => b</div><div>        x = someA -- also works<br></div>    in 0<br><br>This is how it works.  When you write<br><br></div><div>f :: C a => a -> ()<br></div><div>f =<br></div><div>  let x = someA  -- without ':: a'<br>  ()</div><div><br></div><div>The problem is that by not giving an explicit type to x, ghc infers a type and for all intents and purposes it is as though you wrote<br><br><div>f :: C a => a -> ()<br></div><div>f =<br></div><div>  let x :: C a1 => a1<br>      x = someA<br></div><div>      -- also  if you had written x = some :: a, it just means you effectively wrote<br>      -- let x :: C a1 => a1<br>      --     x = someA :: a<br>      -- but 'a1' is not equivalent to 'a', so it errors.<br></div><div>  ()<br><br></div></div><div>And so it says hey wait, a and a1 could be different types.  That is why you often see ghc referring to 'a1' or 'a0' in error messages, because when it infers a type it has to give a name to it in order to report on it.<br><br>What ScopedTypeVariables does is allow you to specify that for the entire scope of this forall, 'a' in any type signature always refers to the same type.<br><br></div><div>f :: forall a. C a => a -> ()<br></div><div>f = undefined<br></div><div>where<br>  some :: a -- this is guaranteed to be the a from above.<br></div><div>  some = undefined<br><br></div><div>  somethingelse :: forall a. a -- this is a different a<br></div><div>  somethingelse = undefined<br></div><div><br></div><div>some :: a -- this toplevel a is of course also different.<br></div><div>some = undefined<br></div><div><br></div><div>So you could just go <br></div><div>{-# LANGUAGE ScopedTypeVariables #-}<br><br>f :: forall a. C a => a -> Int <br>f a = <br>  let <br>     x :: a  -- now the a is the same a as above, so the constraint C a is understood.<br>     x = someA<br></div><div>  in 0<br><br></div><div>I really love the ScopedTypeVariables extension, and so do a lot of other people.  I honestly think it should be on by default because the pitfalls of not having it on are a lot worse than the pitfalls of having it on.  The only pitfall I know of to having it on is that if you have a function with tons of lets and / or wheres, you might not notice you had used the type variable 'a' in two different incompatible places.<br><br></div><div>Hopefully all this makes sense.<br></div><div><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 7, 2017 at 6:41 AM, Baa <span dir="ltr"><<a href="mailto:aquagnu@gmail.com" target="_blank">aquagnu@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello everyone!<br>
<br>
Suppose I have:<br>
<br>
  class C a where<br>
    someA :: a<br>
<br>
  f :: C a => a -> Int<br>
  f a =<br>
    let x = someA :: a in -- BUG!!<br>
      0<br>
<br>
BUG as I understand I due to `:: a` - this is another `a`, not the same as<br>
in `f` singature. But seems that it's the same `a` if `f` is the "method"<br>
of some instance. And such bug does not happen if I return it, so my question<br>
is how to create such `x` of type `a` in the body of the `f`? How to use<br>
`a` anywhere in the body of `f`? Is it possible?<br>
<br>
I found a way if I change signature to `forall a. C a => a -> Int`. But there<br>
are another questions in the case:<br>
<br>
 - as I know all such params are under "forall" in Haskell by-default. Seems<br>
   it's not true?<br>
 - in method body seems they are under "forall" but in simple functions - not?<br>
 - i'm not sure what exactly does this "forall", IMHO it unbounds early bound<br>
   type's variables (parameters) by typechecker, but how `a` can be bound in the<br>
   just begining of signature (where it occurs first time) ?!<br>
<br>
As for me, looks that w/o "forall" all `a`, `b`, `c`, etc in the body of<br>
simple functions always are different types. But w/ "forall" Haskell typechecker<br>
makes something like (on type-level):<br>
<br>
   let a = ANY-TYPE<br>
   in<br>
      ... here `a` can occur and will be bound to ANY-TYPE<br>
<br>
Where am I right and where am I wrong? :)<br>
<br>
===<br>
Best regards, Paul<br>
______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
</blockquote></div><br></div>