<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Yes, indeed. That is precisely what GHC does!<div class=""><br class=""></div><div class="">Well done discovering this. :)</div><div class=""><br class=""></div><div class="">Richard<br class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jan 19, 2022, at 5:34 PM, Benjamin Redelings <<a href="mailto:benjamin.redelings@gmail.com" class="">benjamin.redelings@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" class="">
  
  <div class=""><p class="">1. Hmm... Perhaps ghc changes the code to</p>
    <pre class="">fgtuple:: (Eq a, Num a) => (Char -> a -> Char, Char -> Char -> Char)
fgtuple dEq dNum = 
   let f c i   = if i == 10 then c else g c 'b'
       g 'a' w = f 'b' 10
       g z   w = z
   in (f,g)

f :: forall a. (Eq a, Num) => Char -> a -> Char
f dEq dNum = case fgtuple dEq dNum of (f,g) -> f

g :: Char -> Char -> Char
g = case fgtuple dEqInt dNumInt (f,g) -> g
</pre><p class="">In order words, <br class="">
    </p><p class="">* the definition of fgtuple is not ambiguous.</p><p class="">* the defaulting is applied only to the definition of g, not the
      definition of fgtuple.</p><p class="">Does that sound right?<br class="">
    </p><p class="">2. Running ghc -ddump-tc shows:</p>
    <pre class="">  {Exports: [f <= f_a2gf
               wrap: <>,
             g <= g_a2gi
               wrap: <> @ Integer $dEq_a2xJ $dNum_a2xK]</pre><p class="">The "wrap" code looks like the extra arguments that are applied
      by defaulting.<br class="">
    </p><p class="">-BenRI<br class="">
    </p><p class="">On 1/19/22 11:19 AM, Benjamin Redelings wrote:</p>
    <blockquote type="cite" cite="mid:1ee2fd58-6946-dcce-74f5-4cc2fd5b9590@gmail.com" class="">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8" class=""><p class="">Hi,</p><p class="">I am trying to understand how GHC treats the following
        declaration.<br class="">
      </p>
      <pre class="">f c i   = if i == 10 then c else g c 'b'
g 'a' w = f 'b' 10
g z   w = z

l = (f 'a' (1::Int), f 'a' (1.0::Double))
</pre><p class="">It seems to me like, after defaulting, f should have the
        following type:<br class="">
      </p>
      <pre class="">    Char -> Int -> Char
</pre><p class="">However, looking at -ddump-tc, GHC is deriving the polymorphic
        type <br class="">
      </p>
      <pre class="">    forall a. (Eq a, Num a) => Char -> a -> Char</pre><p class="">That's much nicer, because its more flexible.  But I'm
        confused, because it looks like GHC is defaulting 'g', but not
        'f', even though they are in the same recursive group.  This
        seems to contradict "Typing Haskell in Haskell", which is what I
        am looking at right now.  If that is correct, can anybody point
        me to a paper or documentation about how this works?<br class="">
      </p><p class="">More detail:<br class="">
      </p><p class="">1. If I understand correctly, the definitions of `f` and `g`
        are mutually recursive, and should be typed together, and the
        declaration group is not restricted.<br class="">
      </p><p class="">2. It seems like, before generalization, we have</p>
      <pre class="">    f :: Char -> a -> Char
    g :: Char -> Char -> Char
    Predicates include (Eq a, Num a)
</pre><p class="">3. Looking at the paper "Typing Haskell in Haskell" (THIH), it
        looks like the predicates (Num a, Eq a) should cause an
        ambiguity in the definition of g:<br class="">
      </p><p class="">* a is present in the definition of f, but not the definition
        of g<br class="">
      </p><p class="">* so the type (Eq a, Num a) => Char -> Char -> Char is
        ambiguous.</p><p class="">* more generally, it seems like THIH treats any predicates with
        a type variable that is part of some, but not all, types in the
        declaration group to be ambiguous.  Does this sound right?<br class="">
      </p><p class="">4. Then, again following THIH, this ambiguous predicate should
        be defaulted to Int.<br class="">
      </p><p class="">I THINK this should lead to</p>
      <pre class="">    f :: Char -> Int -> Char
        g :: Char -> Char -> Char
</pre><p class="">5. However, I'm still not sure I'm understanding this right,
        because a few things still don't make sense:<br class="">
      </p><p class="">* First, THIH seems to eliminate the defaulted predicates
        without substituting a -> Int.  But the type for f DOES
        mention `a`, so how can we avoid substituting?<br class="">
      </p><p class="">* Second, GHC accepts the code with no warnings or errors.
        There is some kind of defaulting going on, because GHC rejects
        the code if I add "default ()". Is there some way for GHC to
        default only g, but not f?  <br class="">
      </p><p class="">I wonder if this involves a difference between Haskell '98 and
        Haskell 2010?</p><p class="">I also wonder how much I should rely on THIH?  Maybe the
        language has moved on since then?</p><p class="">-BenRI<br class="">
      </p>
    </blockquote>
  </div>

_______________________________________________<br class="">Haskell-Cafe mailing list<br class="">To (un)subscribe, modify options or view archives go to:<br class=""><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" class="">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br class="">Only members subscribed via the mailman list are allowed to post.</div></blockquote></div><br class=""></div></div></body></html>